From 9305017e819fbfecd7b2aa5aa1749ea4ac9cc720 Mon Sep 17 00:00:00 2001 From: ftillier Date: Tue, 27 Sep 2005 00:03:54 +0000 Subject: [PATCH] [WSD] Update to CM interaction. Added tracking of connections by source/destination IP/port to guarantee unique connections - an undocumented requirement for providers. Signed-off-by: Fab Tillier (ftillier@silverstorm.com) git-svn-id: svn://openib.tc.cornell.edu/gen1@83 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- trunk/ulp/wsd/user/ib_cm.c | 370 +++++++++++++--------------- trunk/ulp/wsd/user/ibsp_duplicate.c | 17 +- trunk/ulp/wsd/user/ibsp_iblow.c | 66 ++++- trunk/ulp/wsd/user/ibspdll.c | 92 +++---- trunk/ulp/wsd/user/ibspdll.rc | 14 +- trunk/ulp/wsd/user/ibspproto.h | 19 +- trunk/ulp/wsd/user/ibspstruct.h | 3 + trunk/ulp/wsd/user/misc.c | 1 + trunk/ulp/wsd/user/sockinfo.c | 2 + 9 files changed, 305 insertions(+), 279 deletions(-) diff --git a/trunk/ulp/wsd/user/ib_cm.c b/trunk/ulp/wsd/user/ib_cm.c index aa4fe7aa..c53b710c 100644 --- a/trunk/ulp/wsd/user/ib_cm.c +++ b/trunk/ulp/wsd/user/ib_cm.c @@ -110,30 +110,20 @@ cm_req_callback( struct ibsp_socket_info *socket_info = (struct ibsp_socket_info * __ptr64)p_cm_req_rec->context; struct listen_incoming *incoming; - ib_rej_status_t rej_status; ib_cm_mra_t mra; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ENTER( IBSP_DBG_CM ); CL_ASSERT( socket_info ); - - if( !p_cm_req_rec->p_req_pdata ) - { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("No private data in CM REQ\n") ); - rej_status = IB_REJ_INSUF_RESOURCES; - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); - return; - } + CL_ASSERT( p_cm_req_rec->p_req_pdata ); incoming = HeapAlloc( g_ibsp.heap, 0, sizeof(struct listen_incoming) ); - if( incoming == NULL ) + if( !incoming ) { /* Low on memory. */ - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("HeapAlloc failed\n") ); - rej_status = IB_REJ_INSUF_RESOURCES; - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); + IBSP_ERROR( ("HeapAlloc failed, rejecting\n") ); + ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_INSUF_RESOURCES ); + IBSP_EXIT( IBSP_DBG_CM ); return; } @@ -150,13 +140,11 @@ cm_req_callback( if( cl_qlist_count( &socket_info->info.listen.list ) >= socket_info->info.listen.backlog ) { /* Already too many connection requests are queued */ - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("already too many incoming connections\n") ); + IBSP_TRACE1( IBSP_DBG_CM, + ("already too many incoming connections, rejecting\n") ); HeapFree( g_ibsp.heap, 0, incoming ); - rej_status = IB_REJ_INSUF_QP; /* or IB_REJ_INSUF_RESOURCES */ - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); - return; + ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED ); + break; } /* Add to the waiting list */ @@ -165,7 +153,7 @@ cm_req_callback( /* Send MRA */ mra.mra_length = 0; mra.p_mra_pdata = NULL; - mra.svc_timeout = 0x1F; + mra.svc_timeout = 0x15; ib_cm_mra( p_cm_req_rec->h_cm_req, &mra ); ibsp_post_select_event( socket_info, FD_ACCEPT, 0 ); @@ -173,68 +161,53 @@ cm_req_callback( case IBSP_DUPLICATING_REMOTE: { - int error; int ret; HeapFree( g_ibsp.heap, 0, incoming ); wait_cq_drain( socket_info ); - ib_destroy_socket( socket_info ); + /* Non-blocking cancel since we're in CM callback context */ + ib_cm_cancel( socket_info->info.listen.handle, NULL ); + socket_info->info.listen.handle = NULL; #if 0 cl_spinlock_release( &socket_info->mutex ); - rej_status = IB_REJ_USER_DEFINED; CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); + ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED ); ibsp_dup_overlap_abort( socket_info ); return; #endif - ret = ib_create_socket( socket_info ); - if( ret ) - { - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, - ("accept failed for duplicate socket (%d)\n", ret) ); - rej_status = IB_REJ_USER_DEFINED; - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); - ibsp_dup_overlap_abort( socket_info ); - return; - } - ret = ib_accept( socket_info, p_cm_req_rec, &error ); + ret = ib_accept( socket_info, p_cm_req_rec ); if( ret ) { cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, - ("accept failed for duplicate socket (%d, %d)\n", ret, error) ); - rej_status = IB_REJ_USER_DEFINED; + IBSP_ERROR( + ("ib_accept for duplicate socket returned %d, rejecting\n", + ret) ); /* Call ib_destroy_socket for above ib_create_socket() call */ ib_destroy_socket( socket_info ); - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); + ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_USER_DEFINED ); ibsp_dup_overlap_abort( socket_info ); + IBSP_EXIT( IBSP_DBG_CM ); return; - } } break; default: - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("socket is not listening anymore\n") ); + IBSP_ERROR( ("socket is not listening anymore\n") ); HeapFree( g_ibsp.heap, 0, incoming ); - rej_status = IB_REJ_INSUF_QP; /* or IB_REJ_INSUF_RESOURCES */ - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("rejecting\n") ); - ib_reject( p_cm_req_rec->h_cm_req, rej_status ); - return; + /* We're closing down - let some other listen match. */ + ib_reject( p_cm_req_rec->h_cm_req, IB_REJ_INVALID_SID ); + break; } cl_spinlock_release( &socket_info->mutex ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } @@ -424,7 +397,7 @@ cm_rtu_callback( cl_spinlock_release( &socket_info->mutex ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } @@ -439,27 +412,32 @@ cm_rej_callback( struct ibsp_socket_info *socket_info = (struct ibsp_socket_info * __ptr64)p_cm_rej_rec->qp_context; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); - - fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__, - __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), socket_info)); + IBSP_ENTER( IBSP_DBG_CM ); - CL_TRACE( IBSP_DBG_CONN, gdbg_lvl, ("connect reject, reason=%d\n", - p_cm_rej_rec->rej_status)); + IBSP_TRACE( IBSP_DBG_CONN, ("socket %p connect reject, reason=%d\n", + socket_info, cl_ntoh16(p_cm_rej_rec->rej_status)) ); cl_spinlock_acquire( &socket_info->mutex ); switch( socket_info->socket_state ) { case IBSP_CONNECT: + /* Remove from connection map. */ + ibsp_conn_remove( socket_info ); + IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND ); - ibsp_post_select_event( socket_info, FD_CONNECT, WSAECONNREFUSED ); + if( p_cm_rej_rec->rej_status == IB_REJ_TIMEOUT ) + ibsp_post_select_event( socket_info, FD_CONNECT, WSAETIMEDOUT ); + else + ibsp_post_select_event( socket_info, FD_CONNECT, WSAECONNREFUSED ); break; case IBSP_ACCEPT: + /* Remove from connection map. */ + ibsp_conn_remove( socket_info ); + IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND ); - SetEvent( socket_info->info.accept.event ); - break; + /* Fall through. */ case IBSP_DUPLICATING_NEW: /* Leave in that state. IBSPSocket will eventually return @@ -468,13 +446,15 @@ cm_rej_callback( break; default: - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("Got an unexpected REJ\n") ); + IBSP_ERROR( ("socket %p got an REJ reason %d in state %s\n", + socket_info, cl_ntoh16( p_cm_rej_rec->rej_status ), + IBSP_SOCKET_STATE_STR(socket_info->socket_state)) ); break; } cl_spinlock_release( &socket_info->mutex ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } @@ -509,70 +489,62 @@ cm_dreq_callback( struct ibsp_socket_info *socket_info = (struct ibsp_socket_info * __ptr64)p_cm_dreq_rec->qp_context; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); - CL_TRACE( IBSP_DBG_CM, gdbg_lvl, - ("cm_dreq_callback: enter, socket_state=%s, socket=%p\n", - IBSP_SOCKET_STATE_STR( socket_info->socket_state ), socket_info) ); + IBSP_ENTER( IBSP_DBG_CM ); + IBSP_TRACE1( IBSP_DBG_CM, + ("socket=%p state=%s\n", + socket_info, IBSP_SOCKET_STATE_STR( socket_info->socket_state )) ); reason = (struct disconnect_reason * __ptr64)p_cm_dreq_rec->p_dreq_pdata; - if( reason->type == DISC_DUPLICATING ) - { - cl_spinlock_acquire( &socket_info->mutex ); + cl_spinlock_acquire( &socket_info->mutex ); - if( socket_info->socket_state == IBSP_CONNECTED ) + if( socket_info->socket_state == IBSP_CONNECTED ) + { + switch( reason->type ) { - int ret; - int error; - - IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_REMOTE ); - socket_info->qp_error = -1; - socket_info->duplicate.identifier = reason->duplicating.identifier; - socket_info->duplicate.dwProcessId = reason->duplicating.dwProcessId; - - /* Now, setup our listening callback. */ - socket_info->info.listen.listen_req_param.dwProcessId = - reason->duplicating.dwProcessId; - socket_info->info.listen.listen_req_param.identifier = - reason->duplicating.identifier; - - ret = ib_listen( socket_info, &error ); - if( ret ) + case DISC_DUPLICATING: { - CL_EXIT_ERROR( IBSP_DBG_CONN, gdbg_lvl, - ("ib_listen failed with %d\n", error) ); - IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED ); - socket_info->qp_error = WSAECONNRESET; + int ret; + int error; + + IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_REMOTE ); + socket_info->qp_error = -1; + socket_info->duplicate.identifier = reason->duplicating.identifier; + socket_info->duplicate.dwProcessId = reason->duplicating.dwProcessId; + + /* Now, setup our listening callback. */ + socket_info->info.listen.listen_req_param.dwProcessId = + reason->duplicating.dwProcessId; + socket_info->info.listen.listen_req_param.identifier = + reason->duplicating.identifier; + + ret = ib_listen( socket_info, &error ); + if( !ret ) + break; + + IBSP_ERROR_EXIT( ("ib_listen failed with %d\n", error) ); + /* Fall through. */ } + default: + /* Right now, treat anything as a normal disconnect. */ + IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED ); + /* We changed the state - remove from connection map. */ + ibsp_conn_remove( socket_info ); + socket_info->qp_error = WSAECONNRESET; } - - cl_spinlock_release( &socket_info->mutex ); } else { - /* Right now, treat anything as a normal disconnect. */ - cl_spinlock_acquire( &socket_info->mutex ); - - if( socket_info->socket_state == IBSP_CONNECTED ) - { - IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DISCONNECTED ); - socket_info->qp_error = WSAECONNRESET; - } - - cl_spinlock_release( &socket_info->mutex ); } + cl_spinlock_release( &socket_info->mutex ); memset( &cm_drep, 0, sizeof(cm_drep) ); status = ib_cm_drep( p_cm_dreq_rec->h_cm_dreq, &cm_drep ); if( status != IB_SUCCESS ) - { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_drep failed (0x%d)\n", status) ); - } - - SetEvent( socket_info->info.disconnect.event ); + IBSP_ERROR( ("ib_cm_drep returned %s\n", ib_get_err_str( status )) ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } @@ -584,15 +556,8 @@ static void AL_API cm_drep_callback( IN ib_cm_drep_rec_t *p_cm_drep_rec ) { - struct ibsp_socket_info *socket_info = - (struct ibsp_socket_info * __ptr64)p_cm_drep_rec->qp_context; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); - - CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("posting DREP event from drep_callback\n") ); - - SetEvent( socket_info->info.disconnect.event ); - + UNUSED_PARAM( p_cm_drep_rec ); CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); } @@ -726,30 +691,27 @@ ib_listen( /* Reject all the queued incoming connection requests. */ -static void -empty_listen_queue( - IN struct ibsp_socket_info *socket_info ) +void +ib_listen_backlog( + IN struct ibsp_socket_info *socket_info, + IN int backlog ) { cl_list_item_t *item; struct listen_incoming *incoming; - // TODO: we don't need to lock anymore, do we? - cl_spinlock_acquire( &socket_info->mutex ); + socket_info->info.listen.backlog = backlog; - for( item = cl_qlist_head( &socket_info->info.listen.list ); - item != cl_qlist_end( &socket_info->info.listen.list ); - item = cl_qlist_head( &socket_info->info.listen.list ) ) + while( + cl_qlist_count( &socket_info->info.listen.list ) > (uint32_t)backlog ) { - incoming = PARENT_STRUCT(item, struct listen_incoming, item); + item = cl_qlist_remove_tail( &socket_info->info.listen.list ); - cl_qlist_remove_item( &socket_info->info.listen.list, &incoming->item ); + incoming = PARENT_STRUCT(item, struct listen_incoming, item); ib_reject( incoming->cm_req_received.h_cm_req, IB_REJ_USER_DEFINED ); HeapFree( g_ibsp.heap, 0, incoming ); } - - cl_spinlock_release( &socket_info->mutex ); } @@ -760,7 +722,7 @@ ib_listen_cancel( { ib_api_status_t status; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ENTER( IBSP_DBG_CM ); /* We should be in the CLOSING state */ CL_ASSERT( socket_info->socket_state == IBSP_CLOSING ); @@ -778,29 +740,41 @@ ib_listen_cancel( /* We can empty the queue now. Since we are closing, * no new entry will be added. */ - empty_listen_queue( socket_info ); + cl_spinlock_acquire( &socket_info->mutex ); + ib_listen_backlog( socket_info, 0 ); + cl_spinlock_release( &socket_info->mutex ); socket_info->info.listen.handle = NULL; - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } int ib_connect( IN struct ibsp_socket_info *socket_info, - IN ib_path_rec_t *path_rec, - OUT LPINT lpErrno ) + IN ib_path_rec_t *path_rec ) { ib_cm_req_t cm_req; ib_api_status_t status; struct cm_req_params params; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ENTER( IBSP_DBG_CM ); fzprint(("%s():%d:0x%x:0x%x: socket=0x%p \n", __FUNCTION__, __LINE__, GetCurrentProcessId(), GetCurrentThreadId(), socket_info)); + CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("From:\n") ); + DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->local_addr ); + CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("To:\n") ); + DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->peer_addr ); + + /* Insert into the connection map. */ + if( !ibsp_conn_insert( socket_info ) ) + { + IBSP_EXIT( IBSP_DBG_CM ); + return WSAEADDRINUSE; + } memset( &cm_req, 0, sizeof(cm_req) ); @@ -821,10 +795,6 @@ ib_connect( CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("connecting to port %d, SID=%016I64x\n", socket_info->peer_addr.sin_port, cm_req.svc_id) ); - CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("From:\n") ); - DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->local_addr ); - CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("To:\n") ); - DebugPrintSockAddr( IBSP_DBG_CM, gdbg_lvl, &socket_info->peer_addr ); cm_req.req_length = sizeof(struct cm_req_params); @@ -859,17 +829,19 @@ ib_connect( status = ib_cm_req( &cm_req ); if( status != IB_SUCCESS ) { - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_req failed (0x%d)\n", status) ); - *lpErrno = ibal_to_wsa_error( status ); - return SOCKET_ERROR; - } + /* Remove from connection map. */ + ibsp_conn_remove( socket_info ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ERROR_EXIT( ("ib_cm_req failed (0x%d)\n", status) ); + return WSAEHOSTUNREACH; + } - *lpErrno = 0; - return 0; + IBSP_EXIT( IBSP_DBG_CM ); + /* Operation is pending */ + return WSAEWOULDBLOCK; } + void ib_reject( IN const ib_cm_handle_t h_cm, @@ -878,32 +850,35 @@ ib_reject( ib_cm_rej_t cm_rej; ib_api_status_t status; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); - - UNUSED_PARAM( rej_status ); + IBSP_ENTER( IBSP_DBG_CM ); memset( &cm_rej, 0, sizeof(cm_rej) ); + cm_rej.rej_status = rej_status; status = ib_cm_rej( h_cm, &cm_rej ); if( status != IB_SUCCESS ) - { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_rej failed (0x%d)\n", status) ); - } + IBSP_ERROR( ("ib_cm_rej returned %s\n", ib_get_err_str( status )) ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } int ib_accept( IN struct ibsp_socket_info *socket_info, - IN ib_cm_req_rec_t *cm_req_received, - OUT LPINT lpErrno ) + IN ib_cm_req_rec_t *cm_req_received ) { ib_cm_rep_t cm_rep; ib_api_status_t status; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ENTER( IBSP_DBG_CM ); + + /* Insert into the connection map. */ + if( !ibsp_conn_insert( socket_info ) ) + { + IBSP_EXIT( IBSP_DBG_CM ); + return WSAEADDRINUSE; + } memset( &cm_rep, 0, sizeof(cm_rep) ); @@ -934,14 +909,16 @@ ib_accept( status = ib_cm_rep( cm_req_received->h_cm_req, &cm_rep ); if( status != IB_SUCCESS ) { - CL_EXIT_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_rep failed (0x%d)\n", status) ); - *lpErrno = ibal_to_wsa_error( status ); - return SOCKET_ERROR; - } + /* Remove from connection map. */ + ibsp_conn_remove( socket_info ); - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_ERROR_EXIT( + ("ib_cm_rep failed (0x%d) at time %I64d\n", + ib_get_err_str( status ), cl_get_time_stamp()) ); + return WSAEACCES; + } - *lpErrno = 0; + IBSP_EXIT( IBSP_DBG_CM ); return 0; } @@ -953,11 +930,9 @@ ib_disconnect( { ib_api_status_t status; ib_cm_dreq_t cm_dreq; - ib_qp_attr_t qp_attr; + ib_qp_mod_t qp_mod; - CL_ENTER( IBSP_DBG_CM, gdbg_lvl ); - - socket_info->info.disconnect.event = CreateEvent( NULL, FALSE, FALSE, NULL ); + IBSP_ENTER( IBSP_DBG_CM ); memset( &cm_dreq, 0, sizeof(cm_dreq) ); @@ -970,47 +945,32 @@ ib_disconnect( status = ib_cm_dreq( &cm_dreq ); - if( status != IB_SUCCESS ) - { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("ib_cm_dreq failed (0x%d)\n", status) ); - goto done; - } - - CL_TRACE( IBSP_DBG_CM, gdbg_lvl, ("wait for DREP event\n") ); - - if( WaitForSingleObject( socket_info->info.disconnect.event, INFINITE ) != WAIT_OBJECT_0 ) + /* + * If both sides initiate disconnection, we might get + * an invalid state or handle here. + */ + if( status != IB_SUCCESS && status != IB_INVALID_STATE && + status != IB_INVALID_HANDLE ) { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, ("WaitForSingleObject failed\n") ); + IBSP_ERROR( ("ib_cm_dreq returned %s\n", ib_get_err_str( status )) ); } - memset( &qp_attr, 0, sizeof(qp_attr) ); - status = ib_query_qp( socket_info->qp, &qp_attr ); + /* + * Note that we don't care about getting the DREP - we move the QP to the + * error state now and flush all posted work requests. If the + * disconnection was graceful, we'll only have the pre-posted receives to + * flush. If the disconnection is ungraceful, we don't care if we + * interrupt transfers. + */ + + /* Force the QP to error state to flush posted receives. */ + memset( &qp_mod, 0, sizeof(qp_mod) ); + qp_mod.req_state = IB_QPS_ERROR; + status = ib_modify_qp( socket_info->qp, &qp_mod ); if( status != IB_SUCCESS ) { - CL_ERROR( IBSP_DBG_EP, gdbg_lvl, ("ib_query_qp failed (%d)\n", status)); - goto done; + socket_info->send_cnt = 0; + socket_info->recv_cnt = 0; } - - if( qp_attr.state != IB_QPS_ERROR ) - { - ib_qp_mod_t qp_mod; - - fzprint(("%s():%d:0x%x:0x%x: socket=0x%p qp state=%d\n", __FUNCTION__, - __LINE__, GetCurrentProcessId(), - GetCurrentThreadId(), socket_info, qp_attr.state)); - memset( &qp_mod, 0, sizeof(qp_mod) ); - qp_mod.req_state = IB_QPS_ERROR; - ib_modify_qp( socket_info->qp, &qp_mod ); - if( status != IB_SUCCESS ) - { - CL_ERROR( IBSP_DBG_CM, gdbg_lvl, - ("ib_mod_qp failed (0x%d)\n", status) ); - } - Sleep( 100 ); - } - -done: - CloseHandle( socket_info->info.disconnect.event ); - - CL_EXIT( IBSP_DBG_CM, gdbg_lvl ); + IBSP_EXIT( IBSP_DBG_CM ); } diff --git a/trunk/ulp/wsd/user/ibsp_duplicate.c b/trunk/ulp/wsd/user/ibsp_duplicate.c index 9e13bf95..b5e3dbd2 100644 --- a/trunk/ulp/wsd/user/ibsp_duplicate.c +++ b/trunk/ulp/wsd/user/ibsp_duplicate.c @@ -61,7 +61,6 @@ setup_duplicate_socket( struct ibsp_duplicate_info *dup_info; ib_net64_t dest_port_guid; ib_path_rec_t path_rec; - int error; CL_ASSERT( socket_info->socket_state == IBSP_CREATE ); @@ -186,8 +185,8 @@ setup_duplicate_socket( socket_info->info.connect.event = CreateEvent( NULL, FALSE, FALSE, NULL ); /* Connects the QP. */ - ret = ib_connect( socket_info, &path_rec, &error ); - if( ret ) + ret = ib_connect( socket_info, &path_rec ); + if( ret != WSAEWOULDBLOCK ) { CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("ib_connect failed (%d)\n", ret) ); goto done; @@ -210,7 +209,7 @@ setup_duplicate_socket( ret = 0; - done: +done: if( h ) CloseHandle( h ); @@ -226,7 +225,10 @@ setup_duplicate_socket( } -/* This function is called by the previous controlling process. */ +/* + * This function is called by the previous controlling process. + * Called with the socket_info->mutex held. + */ int prepare_duplicate_socket( IN struct ibsp_socket_info *socket_info, @@ -245,6 +247,9 @@ prepare_duplicate_socket( CL_ASSERT( socket_info->socket_state == IBSP_CONNECTED ); IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_DUPLICATING_OLD ); + /* We changed the state - remove from connection map. */ + ibsp_conn_remove( socket_info ); + /* We might have a left-over from the previous duplicate. */ if( socket_info->duplicate.mmap_handle != NULL ) { @@ -325,7 +330,9 @@ prepare_duplicate_socket( reason.duplicating.identifier = identifier; reason.duplicating.dwProcessId = dwProcessId; + cl_spinlock_release( &socket_info->mutex ); ib_disconnect( socket_info, &reason ); + cl_spinlock_acquire( &socket_info->mutex ); wait_cq_drain( socket_info ); diff --git a/trunk/ulp/wsd/user/ibsp_iblow.c b/trunk/ulp/wsd/user/ibsp_iblow.c index 49073274..ab14d893 100644 --- a/trunk/ulp/wsd/user/ibsp_iblow.c +++ b/trunk/ulp/wsd/user/ibsp_iblow.c @@ -145,7 +145,6 @@ complete_wq( /* Override the length, as per the WSD specs. */ wr->lpOverlapped->InternalHigh = 0; - socket_info->qp_error = WSAECONNABORTED; break; case IB_WCS_LOCAL_LEN_ERR: @@ -593,7 +592,6 @@ ib_destroy_cq_tinfo( free_wclist, done_wclist) ); } - CL_TRACE( IBSP_DBG_WQ, gdbg_lvl, ("%s():%d:0x%x:0x%x: ib_destroy_cq() start..\n", __FUNCTION__, __LINE__, GetCurrentProcessId(), @@ -1330,3 +1328,67 @@ shutdown_and_destroy_socket_info( CL_EXIT( IBSP_DBG_EP, gdbg_lvl ); } + + +boolean_t +ibsp_conn_insert( + IN struct ibsp_socket_info *s ) +{ + struct ibsp_socket_info *p_sock; + cl_rbmap_item_t *p_item, *p_insert_at; + boolean_t left = TRUE; + + p_item = cl_rbmap_root( &g_ibsp.conn_map ); + p_insert_at = p_item; + + cl_spinlock_acquire( &g_ibsp.socket_info_mutex ); + CL_ASSERT( !s->conn_item.p_map ); + while( p_item != cl_rbmap_end( &g_ibsp.conn_map ) ) + { + p_insert_at = p_item; + p_sock = PARENT_STRUCT( p_item, struct ibsp_socket_info, conn_item ); + if( p_sock->local_addr.sin_family < s->local_addr.sin_family ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->local_addr.sin_family > s->local_addr.sin_family ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else if( p_sock->local_addr.sin_addr.S_un.S_addr < s->local_addr.sin_addr.S_un.S_addr ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->local_addr.sin_addr.S_un.S_addr > s->local_addr.sin_addr.S_un.S_addr ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else if( p_sock->local_addr.sin_port < s->local_addr.sin_port ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->local_addr.sin_port > s->local_addr.sin_port ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else if( p_sock->peer_addr.sin_family < s->peer_addr.sin_family ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->peer_addr.sin_family > s->peer_addr.sin_family ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else if( p_sock->peer_addr.sin_addr.S_un.S_addr < s->peer_addr.sin_addr.S_un.S_addr ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->peer_addr.sin_addr.S_un.S_addr > s->peer_addr.sin_addr.S_un.S_addr ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else if( p_sock->peer_addr.sin_port < s->peer_addr.sin_port ) + p_item = cl_rbmap_left( p_item ), left = TRUE; + else if( p_sock->peer_addr.sin_port > s->peer_addr.sin_port ) + p_item = cl_rbmap_right( p_item ), left = FALSE; + else + goto done; + } + + cl_rbmap_insert( &g_ibsp.conn_map, p_insert_at, &s->conn_item, left ); + +done: + cl_spinlock_release( &g_ibsp.socket_info_mutex ); + return p_item == cl_rbmap_end( &g_ibsp.conn_map ); +} + + +void +ibsp_conn_remove( + IN struct ibsp_socket_info *s ) +{ + cl_spinlock_acquire( &g_ibsp.socket_info_mutex ); + CL_ASSERT( s->conn_item.p_map ); + cl_rbmap_remove_item( &g_ibsp.conn_map, &s->conn_item ); + cl_spinlock_release( &g_ibsp.socket_info_mutex ); +} diff --git a/trunk/ulp/wsd/user/ibspdll.c b/trunk/ulp/wsd/user/ibspdll.c index 8b7bbffa..1d6c9bdb 100644 --- a/trunk/ulp/wsd/user/ibspdll.c +++ b/trunk/ulp/wsd/user/ibspdll.c @@ -466,8 +466,7 @@ reject: /* Update the state of the socket context */ IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_ACCEPT ); - ret = ib_accept( new_socket_info, &incoming->cm_req_received, lpErrno ); - + ret = ib_accept( new_socket_info, &incoming->cm_req_received ); if( ret ) { IBSP_CHANGE_SOCKET_STATE( new_socket_info, IBSP_CREATE ); @@ -770,7 +769,7 @@ IBSPConnect( ib_net64_t dest_port_guid; ib_path_rec_t path_rec; - CL_EXIT( IBSP_DBG_CONN, gdbg_lvl ); + IBSP_ENTER( IBSP_DBG_CONN ); UNUSED_PARAM( lpCalleeData ); UNUSED_PARAM( lpSQOS ); @@ -787,59 +786,66 @@ IBSPConnect( if( lpCallerData ) { /* We don't support that. The current switch does not use it. */ - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("lpCallerData.len=%d\n", lpCallerData->len) ); + IBSP_ERROR_EXIT( ("lpCallerData.len=%d\n", lpCallerData->len) ); *lpErrno = WSAEINVAL; - goto error; + return SOCKET_ERROR; } if( namelen < sizeof(struct sockaddr_in) ) { - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, + IBSP_ERROR_EXIT( ("invalid remote address (%d)\n", socket_info->socket_state) ); *lpErrno = WSAEFAULT; - goto error; + return SOCKET_ERROR; } /* Check if the name (actually address) of peer entity is correct */ if( addr->sin_family != AF_INET || addr->sin_port == 0 || addr->sin_addr.s_addr == INADDR_ANY ) { - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, + IBSP_ERROR_EXIT( ("peer entity address is invalid (%d, %d, %x)\n", addr->sin_family, addr->sin_port, addr->sin_addr.s_addr) ); *lpErrno = WSAEADDRNOTAVAIL; - goto error; + return SOCKET_ERROR; } if( socket_info->local_addr.sin_addr.S_un.S_addr == addr->sin_addr.S_un.S_addr ) { /* Loopback - let the regular stack take care of that. */ - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Loopback!\n") ); + IBSP_ERROR_EXIT( ("Loopback!\n") ); *lpErrno = WSAEADDRNOTAVAIL; - goto error; + return SOCKET_ERROR; } /* Get the GUID for that IP address. */ ret = query_guid_address( socket_info->port, addr->sin_addr.s_addr, &dest_port_guid ); if( ret ) { - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, + IBSP_ERROR_EXIT( ("query_guid_address failed for IP %08x\n", addr->sin_addr.s_addr) ); *lpErrno = WSAEADDRNOTAVAIL; - goto error; + return SOCKET_ERROR; } CL_TRACE( IBSP_DBG_CONN, gdbg_lvl, ("got GUID %I64x for IP %s\n", CL_NTOH64( dest_port_guid ), inet_ntoa( addr->sin_addr )) ); + if( dest_port_guid == socket_info->port->guid ) + { + IBSP_ERROR_EXIT( ("Loopback!\n") ); + *lpErrno = WSAEADDRNOTAVAIL; + return SOCKET_ERROR; + } + /* Get the path record */ ret = query_pr( socket_info->port, dest_port_guid, &path_rec ); if( ret ) { - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, + IBSP_ERROR_EXIT( ("query_pr failed for IP %08x\n", addr->sin_addr.s_addr) ); *lpErrno = WSAEADDRNOTAVAIL; - goto error; + return SOCKET_ERROR; } cl_spinlock_acquire( &socket_info->mutex ); @@ -852,26 +858,20 @@ IBSPConnect( break; case IBSP_CONNECTED: - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Socket is already connected\n") ); + IBSP_ERROR( ("Socket is already connected\n") ); *lpErrno = WSAEISCONN; - goto error; - break; + goto done; case IBSP_LISTEN: - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("Socket is a listening socket\n") ); + IBSP_ERROR( ("Socket is a listening socket\n") ); *lpErrno = WSAEINVAL; - goto error; + goto done; default: - cl_spinlock_release( &socket_info->mutex ); - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, - ("Socket is not in the bound state (%s)\n", + IBSP_ERROR( ("Socket is not in the bound state (%s)\n", IBSP_SOCKET_STATE_STR( socket_info->socket_state )) ); *lpErrno = WSAEINVAL; - goto error; - break; + goto done; } /* Store the peer entity's address in socket context */ @@ -880,34 +880,20 @@ IBSPConnect( /* Update the socket state */ IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_CONNECT ); - cl_spinlock_release( &socket_info->mutex ); - /* Connect */ - ret = ib_connect( socket_info, &path_rec, lpErrno ); - if( ret ) + *lpErrno = ib_connect( socket_info, &path_rec ); + if( *lpErrno != WSAEWOULDBLOCK ) { - cl_spinlock_acquire( &socket_info->mutex ); - - if( socket_info->socket_state == IBSP_CONNECT ) - { - /* We must be sure none destroyed our socket */ - IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND ); - memset( &socket_info->peer_addr, 0, sizeof(struct sockaddr_in) ); - } + /* We must be sure none destroyed our socket */ + IBSP_CHANGE_SOCKET_STATE( socket_info, IBSP_BIND ); + memset( &socket_info->peer_addr, 0, sizeof(struct sockaddr_in) ); - cl_spinlock_release( &socket_info->mutex ); - - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, ("ib_connect failed (%d)\n", ret) ); - - *lpErrno = WSAEHOSTUNREACH; - goto error; + IBSP_ERROR( ("ib_connect failed (%d)\n", *lpErrno) ); } - /* Operation is pending */ - *lpErrno = WSAEWOULDBLOCK; - -error: - CL_EXIT( IBSP_DBG_CONN, gdbg_lvl ); +done: + cl_spinlock_release( &socket_info->mutex ); + IBSP_EXIT( IBSP_DBG_CONN ); return SOCKET_ERROR; } @@ -947,9 +933,9 @@ IBSPDuplicateSocket( *lpErrno = WSAENOTCONN; return SOCKET_ERROR; } - cl_spinlock_release( &socket_info->mutex ); ret = prepare_duplicate_socket( socket_info, dwProcessId ); + cl_spinlock_release( &socket_info->mutex ); if( ret ) { CL_TRACE_EXIT( IBSP_DBG_CONN, gdbg_lvl, @@ -1535,12 +1521,12 @@ IBSPListen( case IBSP_LISTEN: /* Change the backlog */ - socket_info->info.listen.backlog = backlog; + ib_listen_backlog( socket_info, backlog ); *lpErrno = 0; break; default: - CL_ERROR( IBSP_DBG_CONN, gdbg_lvl, + IBSP_ERROR( ("Invalid socket_state (%s)\n", IBSP_SOCKET_STATE_STR( socket_info->socket_state )) ); *lpErrno = WSAEINVAL; diff --git a/trunk/ulp/wsd/user/ibspdll.rc b/trunk/ulp/wsd/user/ibspdll.rc index a752aae0..417606f2 100644 --- a/trunk/ulp/wsd/user/ibspdll.rc +++ b/trunk/ulp/wsd/user/ibspdll.rc @@ -26,21 +26,15 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * - * $Id$ + * $Id: ibspdll.rc 1.3 05/05/23 16:03:31-07:00 ftillier@orbuild.infiniconsys.com $ */ #include #define VER_FILETYPE VFT_DLL #define VER_FILESUBTYPE VFT2_UNKNOWN - -#ifdef _DEBUG_ -#define VER_FILEDESCRIPTION_STR "Winsock Direct for InfiniBand (Debug)" -#else -#define VER_FILEDESCRIPTION_STR "Winsock Direct for InfiniBand" -#endif - -#define VER_INTERNALNAME_STR "ibwsd.dll" -#define VER_ORIGINALFILENAME_STR "ibwsd.dll" +#define VER_FILEDESCRIPTION_STR "SilverStorm Winsock Direct for InfiniBand" +#define VER_INTERNALNAME_STR "ibwsd.dll" +#define VER_ORIGINALFILENAME_STR "ibwsd.dll" #include diff --git a/trunk/ulp/wsd/user/ibspproto.h b/trunk/ulp/wsd/user/ibspproto.h index a9b11227..67b79992 100644 --- a/trunk/ulp/wsd/user/ibspproto.h +++ b/trunk/ulp/wsd/user/ibspproto.h @@ -195,20 +195,23 @@ ib_reject( int ib_accept( IN struct ibsp_socket_info *socket_info, - IN ib_cm_req_rec_t *cm_req_received, - OUT LPINT lpErrno ); + IN ib_cm_req_rec_t *cm_req_received ); int ib_connect( IN struct ibsp_socket_info *socket_info, - IN ib_path_rec_t *path_rec, - OUT LPINT lpErrno ); + IN ib_path_rec_t *path_rec ); void ib_disconnect( IN struct ibsp_socket_info *socket_info, IN struct disconnect_reason *reason ); +void +ib_listen_backlog( + IN struct ibsp_socket_info *socket_info, + IN int backlog ); + /* ibsp_pnp.h */ ib_api_status_t register_pnp( void ); @@ -258,6 +261,14 @@ void ib_deregister_all_mr( IN struct mr_list *mem_list ); +int +ibsp_conn_insert( + IN struct ibsp_socket_info *socket_info ); + +void +ibsp_conn_remove( + IN struct ibsp_socket_info *socket_info ); + void ibsp_post_select_event( struct ibsp_socket_info *socket_info, diff --git a/trunk/ulp/wsd/user/ibspstruct.h b/trunk/ulp/wsd/user/ibspstruct.h index e5d79acd..0172a840 100644 --- a/trunk/ulp/wsd/user/ibspstruct.h +++ b/trunk/ulp/wsd/user/ibspstruct.h @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -210,6 +211,7 @@ struct cq_thread_info struct ibsp_socket_info { cl_list_item_t item; /* Link to next SOCKET_INFO in the global list */ + cl_rbmap_item_t conn_item; cl_spinlock_t mutex; /* protect this structure */ /* Switch socket handle created by WPUCreateSocketHandle. */ @@ -430,6 +432,7 @@ struct ibspdll_globals WSPUPCALLTABLEEX up_call_table; /* MUST keep afetr entry_count */ HANDLE heap; cl_qlist_t socket_info_list; /* List of all the created sockets */ + cl_rbmap_t conn_map; /* rb tree of all connections to ensure unique 4-tuple */ cl_spinlock_t socket_info_mutex; cl_qlist_t closed_socket_info_list; /* List of sockets in IBSP_CLOSED state */ diff --git a/trunk/ulp/wsd/user/misc.c b/trunk/ulp/wsd/user/misc.c index 03f7c117..2ea7ac1c 100644 --- a/trunk/ulp/wsd/user/misc.c +++ b/trunk/ulp/wsd/user/misc.c @@ -104,6 +104,7 @@ init_globals( void ) cl_spinlock_init( &g_ibsp.ip_mutex ); cl_qlist_init( &g_ibsp.socket_info_list ); + cl_rbmap_init( &g_ibsp.conn_map ); cl_spinlock_init( &g_ibsp.socket_info_mutex ); cl_qlist_init( &g_ibsp.closed_socket_info_list ); diff --git a/trunk/ulp/wsd/user/sockinfo.c b/trunk/ulp/wsd/user/sockinfo.c index d008072c..2926235a 100644 --- a/trunk/ulp/wsd/user/sockinfo.c +++ b/trunk/ulp/wsd/user/sockinfo.c @@ -91,6 +91,8 @@ free_socket_info( { IBSP_ENTER( IBSP_DBG_SI ); + CL_ASSERT( !socket_info->conn_item.p_map ); + cl_spinlock_destroy( &socket_info->buf_mem_list.mutex ); cl_spinlock_destroy( &socket_info->mutex ); -- 2.41.0