|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT4 ****************************************
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Copyright (c) 2015, Intel Corporation
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Redistribution and use in source and binary forms, with or without
|
|
Packit |
857059 |
modification, are permitted provided that the following conditions are met:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
* Redistributions of source code must retain the above copyright notice,
|
|
Packit |
857059 |
this list of conditions and the following disclaimer.
|
|
Packit |
857059 |
* Redistributions in binary form must reproduce the above copyright
|
|
Packit |
857059 |
notice, this list of conditions and the following disclaimer in the
|
|
Packit |
857059 |
documentation and/or other materials provided with the distribution.
|
|
Packit |
857059 |
* Neither the name of Intel Corporation nor the names of its contributors
|
|
Packit |
857059 |
may be used to endorse or promote products derived from this software
|
|
Packit |
857059 |
without specific prior written permission.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
Packit |
857059 |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
857059 |
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
Packit |
857059 |
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
Packit |
857059 |
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
857059 |
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
Packit |
857059 |
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
Packit |
857059 |
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
Packit |
857059 |
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
Packit |
857059 |
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
857059 |
|
|
Packit |
857059 |
** END_ICS_COPYRIGHT4 ****************************************/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Public header file
|
|
Packit |
857059 |
#include "ib_cm.h"
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Private header file
|
|
Packit |
857059 |
#include "cm_private.h"
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// Listen
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Prepare CEP for Listening and put on ListenMap
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
// Called with ListLock held, which protects lists and all CEPs
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
Listen(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN CM_LISTEN_INFO* pListenInfo,
|
|
Packit |
857059 |
IN PFN_CM_CALLBACK pfnListenCB,
|
|
Packit |
857059 |
IN void* Context
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, Listen);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If we are binding to a specific port, we need the CaGUID of the port
|
|
Packit |
857059 |
// so that during CmRemoveDevice(), we can cancel this listen
|
|
Packit |
857059 |
pCEP->LocalEndPoint.CaGUID = pListenInfo->CaGUID;
|
|
Packit |
857059 |
ASSERT(! pCEP->bPeer);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Bind address is based on SID with secondary optional
|
|
Packit |
857059 |
// Local/Remote GID/LID and the Private Data Discriminator
|
|
Packit |
857059 |
// (set via CmModifyCEP)
|
|
Packit |
857059 |
// Hence more than one CEP could use the same SID, provided they have unique
|
|
Packit |
857059 |
// combinations of values for the other fields. Values of 0
|
|
Packit |
857059 |
// represent wildcarding the given field (SID can't be wildcarded)
|
|
Packit |
857059 |
pCEP->SID = pListenInfo->ListenAddr.EndPt.SID;
|
|
Packit |
857059 |
pCEP->PrimaryPath.LocalLID = pListenInfo->ListenAddr.Port.LID;
|
|
Packit |
857059 |
pCEP->PrimaryPath.LocalGID = pListenInfo->ListenAddr.Port.GID;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEP->PrimaryPath.RemoteLID = pListenInfo->RemoteAddr.Port.LID;
|
|
Packit |
857059 |
pCEP->PrimaryPath.RemoteGID = pListenInfo->RemoteAddr.Port.GID;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEP->LocalEndPoint.QPN = pCEP->LocalEndPoint.EECN = 0;
|
|
Packit |
857059 |
pCEP->RemoteEndPoint.QPN = pCEP->RemoteEndPoint.EECN = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// add to ListenMap and make sure bound address is unique
|
|
Packit |
857059 |
if (! CM_MapTryInsert(&gCM->ListenMap, (uintn)pCEP, &pCEP->MapEntry, "LISTEN_LIST", pCEP))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> Address in use!!!\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
// clear out CEP fields
|
|
Packit |
857059 |
MemoryClear(&pCEP->LocalEndPoint, sizeof(pCEP->LocalEndPoint));
|
|
Packit |
857059 |
MemoryClear(&pCEP->RemoteEndPoint, sizeof(pCEP->RemoteEndPoint));
|
|
Packit |
857059 |
MemoryClear(&pCEP->PrimaryPath, sizeof(pCEP->PrimaryPath));
|
|
Packit |
857059 |
pCEP->LocalEndPoint.CaGUID = 0;
|
|
Packit |
857059 |
pCEP->SID = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return FCM_ADDR_INUSE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// LocalCommID for listening CEP is used only for debugging purposes
|
|
Packit |
857059 |
AssignLocalCommID(pCEP);
|
|
Packit |
857059 |
pCEP->TransactionID = 0; // not used, will use TID of remote client
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> Comm ID set at <lcid 0x%x>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), pCEP->LocalCommID));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEP->Mode = CM_MODE_PASSIVE;
|
|
Packit |
857059 |
pCEP->LocalCMTimeout = 0;
|
|
Packit |
857059 |
pCEP->RemoteCMTimeout = 0;
|
|
Packit |
857059 |
pCEP->MaxCMRetries = 0;
|
|
Packit |
857059 |
pCEP->EventFlags = 0;
|
|
Packit |
857059 |
pCEP->RetryCount = 0;
|
|
Packit |
857059 |
//pCEP->pWaitEvent = NULL;
|
|
Packit |
857059 |
DListInit(&pCEP->PendingList);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pCEP->pDgrmElement)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Return the datagram since listen objects do not use it
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> Releasing the dgrm <dgrm 0x%p>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(pCEP->pDgrmElement)));
|
|
Packit |
857059 |
CmDgrmRelease(pCEP->pDgrmElement);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Save user callback info
|
|
Packit |
857059 |
pCEP->pfnUserCallback = pfnListenCB;
|
|
Packit |
857059 |
pCEP->UserContext = Context;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
CepSetState(pCEP, CMS_LISTEN);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Listening on <sid 0x%"PRIx64" lid 0x%x gid 0x%"PRIx64":0x%"PRIx64">.***\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), pListenInfo->ListenAddr.EndPt.SID,
|
|
Packit |
857059 |
pListenInfo->ListenAddr.Port.LID,
|
|
Packit |
857059 |
pCEP->PrimaryPath.LocalGID.Type.Global.SubnetPrefix,
|
|
Packit |
857059 |
pCEP->PrimaryPath.LocalGID.Type.Global.InterfaceID));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// At this point, we are listening for incoming connections on this obj.
|
|
Packit |
857059 |
return FPENDING;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // Listen()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// See GetConnInfo in cm_active.c for callback processing
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// WaitP
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS or FTIMEOUT.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
WaitP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
OUT CM_CONN_INFO* pConnInfo,
|
|
Packit |
857059 |
uint32 Timeout_us // TODO: Put a max limit on this in addition to infinite
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
uint32 WaitTimeUs=Timeout_us;
|
|
Packit |
857059 |
uint64 TimeoutUs=Timeout_us;
|
|
Packit |
857059 |
uint64 StartTimeUs=GetTimeStamp();
|
|
Packit |
857059 |
|
|
Packit |
857059 |
uint64 CurrTimeUs=0;
|
|
Packit |
857059 |
uint64 TimeElapsedUs=0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//CMM_MSG* pMsg=&((CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement))->payload;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, WaitP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
waitagain:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Update the timeout
|
|
Packit |
857059 |
if ((int32)WaitTimeUs != EVENT_NO_TIMEOUT)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (CurrTimeUs >= StartTimeUs)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
TimeElapsedUs = (CurrTimeUs - StartTimeUs);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else // wrap-around
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
TimeElapsedUs = (CurrTimeUs + ((uint64)(-1) - StartTimeUs));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (TimeoutUs > TimeElapsedUs)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
WaitTimeUs = (uint32) (TimeoutUs - TimeElapsedUs);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
WaitTimeUs = 0;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//_DBG_INFO(("<cep 0x%p> Waiting on obj... <timeout %ums lcid 0x%x %s>\n",
|
|
Packit |
857059 |
// _DBG_PTR(pCEP), WaitTimeUs/1000, pCEP->LocalCommID,
|
|
Packit |
857059 |
// _DBG_PTR(CmGetStateString(pCEP->State))));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = EventWaitOn(pCEP->pEventObj, WaitTimeUs);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//_DBG_INFO(("<cep 0x%p> Waiting on obj... complete <%s %s>\n",
|
|
Packit |
857059 |
// _DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status)),
|
|
Packit |
857059 |
// _DBG_PTR(CmGetStateString(pCEP->State))));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (Status == FTIMEOUT)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (Timeout_us == 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
//_DBG_INFO(("<cep 0x%p> Obj state is nonsignaled.\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> EventWaitOn() returns FTIMEOUT!\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return FTIMEOUT;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ASSERT(Status == FSUCCESS);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> Obj state is signaled <%s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(CmGetStateString(pCEP->State))));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Get mutual ex to the object
|
|
Packit |
857059 |
SpinLockAcquire(&gCM->ListLock);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = GetConnInfo(pCEP, pConnInfo);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (Status != FSUCCESS)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Handle the case when we get signal but we already process the event
|
|
Packit |
857059 |
// with the previous signal
|
|
Packit |
857059 |
// eg evt1 --> signal; evt2 --> signal
|
|
Packit |
857059 |
// ->wait() returned
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> GetConnInfo() returns %s!\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ASSERT(pConnInfo->Status == 0);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
SpinLockRelease(&gCM->ListLock);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
goto waitagain;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
SpinLockRelease(&gCM->ListLock);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // WaitP()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// given a CEP for which a FCM_CONNECT_REQUEST has been reported
|
|
Packit |
857059 |
// fetch the head of the pending list
|
|
Packit |
857059 |
static FSTATUS
|
|
Packit |
857059 |
GetPendingCEP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
OUT CM_CEP_OBJECT** ppCEPEntry
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
CM_CEP_OBJECT* pCEPEntry = NULL;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
DLIST_ENTRY* pListEntry=NULL;
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, GetPendingCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
switch (pCEP->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_IDLE:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (BitTest(pCEP->EventFlags, USRE_CANCEL))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// User cancelled the listen, but hasn't gotten callback yet
|
|
Packit |
857059 |
Status = FCM_CONNECT_CANCEL;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case CMS_LISTEN:
|
|
Packit |
857059 |
case CMS_REQ_RCVD: // separate out for Peer, no PendingList need then
|
|
Packit |
857059 |
case CMS_MRA_REQ_SENT: // separate out for Peer, no PendingList need then
|
|
Packit |
857059 |
// could have listen get the pCEPEntry and then have common code
|
|
Packit |
857059 |
// with Peer REQ_RCVD/MRA_REQ_SENT cases
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Accepting new client or peer connection
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
if (pCEP->bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Accepting peer connection ***\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Accepting client connection ***\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (DListIsEmpty(&pCEP->PendingList))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// If user reject() or cancel() and then call accept()
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> Pending list is empty!\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
Status = FNOT_FOUND;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Note: For peer-to-peer connection (bPeer == TRUE), the entry in the PENDING list
|
|
Packit |
857059 |
// is the same as the one passed in i.e. pCEP == pCEPEntry
|
|
Packit |
857059 |
pListEntry = DListGetNext(&pCEP->PendingList);
|
|
Packit |
857059 |
pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
|
|
Packit |
857059 |
ASSERT(pCEPEntry->pParentCEP == pCEP);
|
|
Packit |
857059 |
if (pCEP->bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ASSERT(pCEPEntry == pCEP);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
ASSERT(pCEPEntry != pCEP);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Cannot accept until the user has been notify thru wait
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> Cannot accept - User must call wait() before accept()!\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP)));
|
|
Packit |
857059 |
// Re-signal
|
|
Packit |
857059 |
EventSet(pCEP, CME_RCVD_REQ);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = FUNAVAILABLE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
BitClear(pCEPEntry->EventFlags, USRE_WAIT);
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Make sure we havent timed-out or receive a reject
|
|
Packit |
857059 |
switch (pCEPEntry->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_REQ_RCVD:
|
|
Packit |
857059 |
case CMS_MRA_REQ_SENT:
|
|
Packit |
857059 |
*ppCEPEntry = pCEPEntry;
|
|
Packit |
857059 |
Status = FSUCCESS;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
} // switch()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // GetPendingCEP
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// process an inbound REQ for a passive CEP
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
ProcessRequestP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN CM_REP_FAILOVER Failover,
|
|
Packit |
857059 |
OUT CM_PROCESS_REQUEST_INFO *Info
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status;
|
|
Packit |
857059 |
IB_CA_ATTRIBUTES *pCaAttr = NULL;
|
|
Packit |
857059 |
CM_CEP_OBJECT* pCEPEntry;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessRequestP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// TBD - RD code here is not complete/accurate
|
|
Packit |
857059 |
ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = GetPendingCEP(pCEP, &pCEPEntry);
|
|
Packit |
857059 |
if (Status != FSUCCESS)
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
if (pCEPEntry->Type == CM_UD_TYPE)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (Info == NULL)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_PARAMETER;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
MemoryClear(Info, sizeof(*Info)); // just to be safe
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Child must inherit parent's setting for now
|
|
Packit |
857059 |
// Will be saved again when AcceptP
|
|
Packit |
857059 |
pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// get ca Attr
|
|
Packit |
857059 |
pCaAttr = (IB_CA_ATTRIBUTES*)MemoryAllocate(sizeof(*pCaAttr), FALSE, CM_MEM_TAG);
|
|
Packit |
857059 |
if (pCaAttr == NULL)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINSUFFICIENT_MEMORY;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
pCaAttr->PortAttributesListSize = 0;
|
|
Packit |
857059 |
pCaAttr->PortAttributesList = NULL;
|
|
Packit |
857059 |
Status = iba_query_ca_by_guid(pCEPEntry->LocalEndPoint.CaGUID, pCaAttr);
|
|
Packit |
857059 |
if (Status != FINSUFFICIENT_MEMORY && Status != FSUCCESS)
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// set up attributes to move QP to Init
|
|
Packit |
857059 |
GetInitAttrFromCep(pCEPEntry, &Info->QpAttrInit);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// update LocalResponder/Initiator/SendPSN so we are ready in case
|
|
Packit |
857059 |
// application calls iba_cm_prepare_rts before doing iba_cm_accept
|
|
Packit |
857059 |
// Build Reply
|
|
Packit |
857059 |
pCEPEntry->LocalRecvPSN = Info->ReplyInfo.Info.Reply.StartingPSN =
|
|
Packit |
857059 |
GenerateStartPSN();
|
|
Packit |
857059 |
// RDMA Read is not supported for UC, leave zero
|
|
Packit |
857059 |
if (pCEPEntry->Type != CM_UC_TYPE) {
|
|
Packit |
857059 |
pCEPEntry->LocalResponderResources =
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.ArbResponderResources =
|
|
Packit |
857059 |
MIN(pCEPEntry->LocalResponderResources,
|
|
Packit |
857059 |
pCaAttr->MaxQPResponderResources);
|
|
Packit |
857059 |
pCEPEntry->LocalInitiatorDepth =
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.ArbInitiatorDepth =
|
|
Packit |
857059 |
MIN(pCEPEntry->LocalInitiatorDepth,
|
|
Packit |
857059 |
pCaAttr->MaxQPInitiatorDepth);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.TargetAckDelay = pCaAttr->LocalCaAckDelay;
|
|
Packit |
857059 |
// spec implies we should say NOT_SUPPORTED even if no alternate path
|
|
Packit |
857059 |
// was provided in REQ
|
|
Packit |
857059 |
if (pCaAttr->PathMigrationLevel == CAPathMigNone
|
|
Packit |
857059 |
|| ! pCEPEntry->bFailoverSupported)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.FailoverAccepted = CM_REP_FO_NOT_SUPPORTED;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.FailoverAccepted = Failover;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
// end to end credits and RNR not allowed for UC
|
|
Packit |
857059 |
if (pCEPEntry->Type != CM_UC_TYPE) {
|
|
Packit |
857059 |
// our CA supports RC credits
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.EndToEndFlowControl = TRUE;
|
|
Packit |
857059 |
Info->ReplyInfo.Info.Reply.RnRRetryCount =
|
|
Packit |
857059 |
pCEPEntry->LocalRnrRetryCount; // 1st guess
|
|
Packit |
857059 |
// caller must set approprite RnrRetryCount, this is just
|
|
Packit |
857059 |
// a wild guess, caller can set higher or lower
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// set up attributes to move QP to RTR
|
|
Packit |
857059 |
GetRtrAttrFromCep(pCEPEntry,
|
|
Packit |
857059 |
(Info->ReplyInfo.Info.Reply.FailoverAccepted == CM_REP_FO_ACCEPTED),
|
|
Packit |
857059 |
&Info->QpAttrRtr);
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
if (pCaAttr)
|
|
Packit |
857059 |
MemoryDeallocate(pCaAttr);
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// AcceptP_Async
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS - The function has completed successfully. For server, this indicates the initialization.
|
|
Packit |
857059 |
// >FCM_CONNECT_ESTABLISHED
|
|
Packit |
857059 |
// >FCM_CONNECT_REJECT
|
|
Packit |
857059 |
// >FCM_CONNECT_TIMEOUT
|
|
Packit |
857059 |
// >FCM_CONNECT_CANCEL
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FINVALID_STATE - The endpoint is not in the valid state for this call
|
|
Packit |
857059 |
// FERROR - Unable to send the reply ack packet
|
|
Packit |
857059 |
// FTIMEOUT - The timeout interval expires
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
AcceptP_Async(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN const CM_CONN_INFO* pSendConnInfo, // Send REP
|
|
Packit |
857059 |
IN EVENT_HANDLE hEvent,
|
|
Packit |
857059 |
IN EVENT_HANDLE hWaitEvent,
|
|
Packit |
857059 |
IN PFN_CM_CALLBACK pfnCallback,
|
|
Packit |
857059 |
IN void* Context,
|
|
Packit |
857059 |
IN boolean willWait,
|
|
Packit |
857059 |
OUT CM_CEP_OBJECT** ppCEP
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
CM_CEP_OBJECT* pCEPEntry = NULL;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
uint32 rep_timeout_ms=0;
|
|
Packit |
857059 |
uint64 elapsed_us=0;
|
|
Packit |
857059 |
uint8 timewait;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AcceptP_Async);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (ppCEP)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
*ppCEP = NULL;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check QPN/EECN has been supplied
|
|
Packit |
857059 |
if (! pSendConnInfo || (pSendConnInfo->Info.Reply.QPN == 0
|
|
Packit |
857059 |
&& pSendConnInfo->Info.Reply.EECN == 0))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_PARAMETER;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
SpinLockAcquire(&gCM->ListLock);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = GetPendingCEP(pCEP, &pCEPEntry);
|
|
Packit |
857059 |
if (Status != FSUCCESS)
|
|
Packit |
857059 |
goto unlock;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//BitClear(pCEPEntry->EventFlags, CME_REQ_RCVD);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
elapsed_us = CmGetElapsedTime(pCEPEntry);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Update the turnaround time
|
|
Packit |
857059 |
gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("Update turnaround time <tat %"PRIu64"us>.\n", gCM->turnaround_time_us));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// check RDMA Read parameters have not been incorrectly increased
|
|
Packit |
857059 |
if (pCEPEntry->LocalInitiatorDepth <
|
|
Packit |
857059 |
pSendConnInfo->Info.Reply.ArbInitiatorDepth
|
|
Packit |
857059 |
|| pCEPEntry->LocalResponderResources <
|
|
Packit |
857059 |
pSendConnInfo->Info.Reply.ArbResponderResources)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_PARAMETER;
|
|
Packit |
857059 |
goto unlock;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pCEPEntry->bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// API design decision, must use same EndPoint in CmAccept
|
|
Packit |
857059 |
// as did in original PeerConnect. We enforce this
|
|
Packit |
857059 |
// (as opposed to blindly replacing Reply or CEP info)
|
|
Packit |
857059 |
// to catch applications which end up with 2 QPs for the CEP
|
|
Packit |
857059 |
if (pCEPEntry->LocalEndPoint.QPN != pSendConnInfo->Info.Reply.QPN
|
|
Packit |
857059 |
|| pCEPEntry->LocalEndPoint.EECN != pSendConnInfo->Info.Reply.EECN)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_PARAMETER;
|
|
Packit |
857059 |
goto unlock;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
// Save the relevent user reply info to this object
|
|
Packit |
857059 |
pCEPEntry->LocalEndPoint.QPN = pSendConnInfo->Info.Reply.QPN;
|
|
Packit |
857059 |
pCEPEntry->LocalEndPoint.EECN = pSendConnInfo->Info.Reply.EECN;
|
|
Packit |
857059 |
if (! CM_MapTryInsert(&gCM->LocalEndPointMap, (uintn)pCEPEntry,
|
|
Packit |
857059 |
&pCEPEntry->LocalEndPointMapEntry, "LOCAL_END_POINT_LIST", pCEPEntry))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FCM_ADDR_INUSE;
|
|
Packit |
857059 |
pCEPEntry->LocalEndPoint.QPN = 0;
|
|
Packit |
857059 |
pCEPEntry->LocalEndPoint.EECN = 0;
|
|
Packit |
857059 |
goto unlock;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Save the disconnect callback
|
|
Packit |
857059 |
pCEPEntry->pfnUserCallback = pfnCallback;
|
|
Packit |
857059 |
pCEPEntry->UserContext = Context;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEPEntry->bAsyncAccept = pCEP->bAsyncAccept;
|
|
Packit |
857059 |
pCEPEntry->bTimewaitCallback = pCEP->bTimewaitCallback;
|
|
Packit |
857059 |
pCEPEntry->bFailoverSupported = pCEP->bFailoverSupported;
|
|
Packit |
857059 |
pCEPEntry->turnaround_time_us = pCEP->turnaround_time_us;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Use this user-specified event obj instead of the one we created internally
|
|
Packit |
857059 |
if (hEvent)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
OS_WAIT_OBJ_HANDLE hCEPEventObj = (OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj;
|
|
Packit |
857059 |
boolean RemoveReference = FALSE;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (hCEPEventObj)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (pCEPEntry->bPrivateEvent)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
EventDealloc(pCEPEntry->pEventObj);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
RemoveReference = TRUE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEPEntry->bPrivateEvent = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pCEPEntry->pEventObj = (EVENT*)hEvent;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
OsWaitObjAddRef((OS_WAIT_OBJ_HANDLE)pCEPEntry->pEventObj);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (RemoveReference)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
OsWaitObjRemoveRef(hCEPEventObj);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (hWaitEvent)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
pCEPEntry->pWaitEvent = (EVENT*)hWaitEvent;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pCEP->AlternatePath.LocalLID != 0)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (pSendConnInfo->Info.Reply.FailoverAccepted != CM_REP_FO_ACCEPTED)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
MemoryClear(&pCEP->AlternatePath, sizeof(pCEP->AlternatePath));
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
pCEPEntry->bFailoverSupported &= IsFailoverSupported(
|
|
Packit |
857059 |
pSendConnInfo->Info.Reply.FailoverAccepted);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// save arbitrated RDMA Read parameters
|
|
Packit |
857059 |
pCEPEntry->LocalInitiatorDepth =
|
|
Packit |
857059 |
pSendConnInfo->Info.Reply.ArbInitiatorDepth;
|
|
Packit |
857059 |
pCEPEntry->LocalResponderResources =
|
|
Packit |
857059 |
pSendConnInfo->Info.Reply.ArbResponderResources;
|
|
Packit |
857059 |
if (pSendConnInfo->Info.Reply.TargetAckDelay > pCEP->TargetAckDelay)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
pCEP->TargetAckDelay = pSendConnInfo->Info.Reply.TargetAckDelay;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
pCEP->LocalRecvPSN = pSendConnInfo->Info.Reply.StartingPSN;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// update timewait
|
|
Packit |
857059 |
// some applications don't set TargetAckDelay properly
|
|
Packit |
857059 |
// and to be safe we want our timewait to be no less than remote end
|
|
Packit |
857059 |
// so be conservative and only increase it, the computation below
|
|
Packit |
857059 |
// due to the round up of PktLifeTime, essentially always
|
|
Packit |
857059 |
// adds TargetAckDelay to the timewait
|
|
Packit |
857059 |
timewait = TimeoutTimeToMult(
|
|
Packit |
857059 |
(TimeoutMultToTimeInUsec(pCEPEntry->PktLifeTime)<<1)
|
|
Packit |
857059 |
+ TimeoutMultToTimeInUsec(pCEP->TargetAckDelay));
|
|
Packit |
857059 |
if (pCEPEntry->Timewait < timewait)
|
|
Packit |
857059 |
pCEPEntry->Timewait = timewait;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
FormatREP((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement),
|
|
Packit |
857059 |
&pSendConnInfo->Info.Reply,
|
|
Packit |
857059 |
pCEPEntry->TransactionID,
|
|
Packit |
857059 |
pCEPEntry->LocalCommID,
|
|
Packit |
857059 |
pCEPEntry->RemoteCommID,
|
|
Packit |
857059 |
pCEPEntry->LocalEndPoint.CaGUID);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> REP's dgrm address field <portguid 0x%"PRIx64", dlid 0x%x, slm %d, pathbits %d, rate %d>\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEPEntry),
|
|
Packit |
857059 |
pCEPEntry->pDgrmElement->PortGuid,
|
|
Packit |
857059 |
pCEPEntry->pDgrmElement->RemoteLID,
|
|
Packit |
857059 |
pCEPEntry->pDgrmElement->ServiceLevel,
|
|
Packit |
857059 |
pCEPEntry->pDgrmElement->PathBits,
|
|
Packit |
857059 |
pCEPEntry->pDgrmElement->StaticRate));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Send out the REP
|
|
Packit |
857059 |
Status = CmDgrmSend(pCEPEntry->pDgrmElement);
|
|
Packit |
857059 |
if (FSUCCESS != Status)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// fall through and let timer retry the send later
|
|
Packit |
857059 |
_DBG_WARN(("<cep 0x%p> DgrmSend() failed for REP!!! <%s>\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
Status = FSUCCESS;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
AtomicIncrementVoid(&gCM->Sent.Rep);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> REP sent <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID,
|
|
Packit |
857059 |
pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
CepRemoveFromPendingList(pCEPEntry);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
CepSetState(pCEPEntry, CMS_REP_SENT);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// For peer connection, leave the entry in the LISTEN list
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Start timer to timeout the REP i.e. wait for the RTU msg to arrive
|
|
Packit |
857059 |
pCEPEntry->RetryCount = 0;
|
|
Packit |
857059 |
rep_timeout_ms = TimeoutMultToTimeInMs(pCEPEntry->LocalCMTimeout);
|
|
Packit |
857059 |
CmTimerStart(pCEPEntry, rep_timeout_ms, REP_TIMER);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (willWait)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// caller will be doing a WaitP
|
|
Packit |
857059 |
// prevent a callback until caller WaitP completes
|
|
Packit |
857059 |
AtomicIncrementVoid(&pCEPEntry->CallbackRefCnt);
|
|
Packit |
857059 |
AtomicIncrementVoid(&gCM->TotalCallbackRefCnt);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If another connection is pending for this server endpoint,
|
|
Packit |
857059 |
// we must set it again to wake up the Wait()
|
|
Packit |
857059 |
if (pCEP->PendingCount)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Return the new CEP object to the user
|
|
Packit |
857059 |
if (ppCEP)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
*ppCEP = pCEPEntry;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
Status = FPENDING;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
unlock:
|
|
Packit |
857059 |
SpinLockRelease(&gCM->ListLock);
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // AcceptP_Asynch()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// AcceptP
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FCM_CONNECT_ESTABLISHED - Connection established
|
|
Packit |
857059 |
// FCM_CONNECT_REJECT - Connection rejected
|
|
Packit |
857059 |
// FCM_CONNECT_TIMEOUT - Connection timeout
|
|
Packit |
857059 |
// FCM_CONNECT_CANCEL - Connection cancel
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FINVALID_STATE - The endpoint is not in the valid state for this call
|
|
Packit |
857059 |
// FERROR - Nothing to accept, cannot accept, or unable to send the reply packet
|
|
Packit |
857059 |
// FTIMEOUT - The timeout interval expires
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
AcceptP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN const CM_CONN_INFO* pSendConnInfo, // Send REP
|
|
Packit |
857059 |
OUT CM_CONN_INFO* pRecvConnInfo, // Rcvd RTU, REJ or TIMEOUT
|
|
Packit |
857059 |
IN PFN_CM_CALLBACK pfnCallback,
|
|
Packit |
857059 |
IN void* Context,
|
|
Packit |
857059 |
OUT CM_CEP_OBJECT** ppNewCEP
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
CM_CEP_OBJECT* pNewCEP=NULL;
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
uint32 rep_timeout_ms=0;
|
|
Packit |
857059 |
boolean bPeer = pCEP->bPeer; // save in case move Cep to Idle
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_EXT(_DBG_LVL_FUNC_TRACE, AcceptP, == PASSIVE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
UNUSED_VAR(rep_timeout_ms);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (! pRecvConnInfo && ! pCEP->bAsyncAccept)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FINVALID_PARAMETER;
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
// Accept client or peer connection. Send the REP to the remote client
|
|
Packit |
857059 |
// use ppNewCEP if not-NULL so caller gets updated while in Lock in
|
|
Packit |
857059 |
// AcceptP_Async
|
|
Packit |
857059 |
Status = AcceptP_Async(pCEP, pSendConnInfo, NULL, NULL, pfnCallback, Context, ! pCEP->bAsyncAccept, ppNewCEP?ppNewCEP:&pNewCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (Status != FSUCCESS && Status != FPENDING)
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
if (ppNewCEP)
|
|
Packit |
857059 |
pNewCEP = *ppNewCEP;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
ASSERT(pNewCEP == pCEP);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pCEP->bAsyncAccept)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// we will provide a callback when RTU or REJ arrives or timeout
|
|
Packit |
857059 |
goto done;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Wait for RTU or REJ to arrive or timeout event to occur
|
|
Packit |
857059 |
// TODO: We should put a time limit here in case we dont get the timeout event ??
|
|
Packit |
857059 |
Status = WaitP(pNewCEP, pRecvConnInfo, EVENT_NO_TIMEOUT);
|
|
Packit |
857059 |
//rep_timeout_ms = TimeoutMultToTimeInMs(pNewCEP->LocalCMTimeout);
|
|
Packit |
857059 |
//Status = WaitP(pNewCEP, pRecvConnInfo, 2*rep_timeout_ms, TRUE);
|
|
Packit |
857059 |
ASSERT(Status == FSUCCESS);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// This is the status we returned to the caller
|
|
Packit |
857059 |
Status = pRecvConnInfo->Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Check the status here instead of the state since the status is what
|
|
Packit |
857059 |
// we return to the caller
|
|
Packit |
857059 |
if (Status == FCM_CONNECT_ESTABLISHED)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Note: Though the status is established, the pNewCEP state may not be in
|
|
Packit |
857059 |
// CMS_ESTABLISHED since we may have already received a DREQ
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Connection established *** <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
pNewCEP->PrimaryPath.LocalLID, pNewCEP->PrimaryPath.RemoteLID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State))));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
switch (Status)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case FCM_CONNECT_CANCEL: // USRE_CANCEL
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Connection cancelled *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case FCM_CONNECT_REJECT: // CME_RCVD_REJ
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Connection rejected *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case FCM_CONNECT_TIMEOUT: // CME_TIMEOUT_REP
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Connection timed out *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case FCM_DISCONNECT_REQUEST:
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Disconnecting *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case FCM_DISCONNECTED:
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Disconnected *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> *** Connection ??? *** <lcid 0x%x rcid 0x%x %s %s>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pNewCEP), pNewCEP->LocalCommID, pNewCEP->RemoteCommID,
|
|
Packit |
857059 |
_DBG_PTR(CmGetStateString(pNewCEP->State)), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
ASSERT(0);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // switch()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (!bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// This is the one we created when a new connection request arrived
|
|
Packit |
857059 |
iba_cm_destroy_cep(pNewCEP);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
if (ppNewCEP)
|
|
Packit |
857059 |
*ppNewCEP = NULL;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
CmDoneCallback(pNewCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
done:
|
|
Packit |
857059 |
_DBG_LEAVE_EXT(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // AcceptP()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// RejectP
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
RejectP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN const CM_REJECT_INFO* pConnectReject
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
CM_CEP_OBJECT* pCEPEntry = NULL;
|
|
Packit |
857059 |
DLIST_ENTRY* pListEntry=NULL;
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
boolean bPeer = pCEP->bPeer; // in case move Cep to Idle
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, RejectP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
switch (pCEP->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_IDLE:
|
|
Packit |
857059 |
if (BitTest(pCEP->EventFlags, USRE_CANCEL))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// User cancelled the listen, but hasn't gotten callback yet
|
|
Packit |
857059 |
Status = FCM_CONNECT_CANCEL;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case CMS_LISTEN:
|
|
Packit |
857059 |
case CMS_REQ_RCVD: // TBD only occurs for actual CEP (can be Peer), separate out
|
|
Packit |
857059 |
case CMS_MRA_REQ_SENT: // TBD only occurs for actual CEP (can be Peer), separate out
|
|
Packit |
857059 |
// if separate out above and did same in AcceptP, won't need Peer on PendingList
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Rejecting the incoming connect or peer request
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
if (DListIsEmpty(&pCEP->PendingList))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Nothing to reject
|
|
Packit |
857059 |
_DBG_WARNING(("<cep 0x%p> Pending list is empty!\n", _DBG_PTR(pCEP)));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = FNOT_FOUND;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Pull the incoming connection
|
|
Packit |
857059 |
pListEntry = DListGetNext(&pCEP->PendingList);
|
|
Packit |
857059 |
pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
|
|
Packit |
857059 |
ASSERT(pCEPEntry->pParentCEP == pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Cannot reject until the user has been notify thru wait
|
|
Packit |
857059 |
/*
|
|
Packit |
857059 |
if (!BitTest(pCEPEntry->EventFlags, USRE_WAIT))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
Status = FUNAVAILABLE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
BitClear(pCEPEntry->EventFlags, USRE_WAIT);
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ASSERT(pCEPEntry->State == CMS_REQ_RCVD || pCEPEntry->State == CMS_MRA_REQ_SENT);
|
|
Packit |
857059 |
// Format the REJ msg
|
|
Packit |
857059 |
FormatREJ((CM_MAD*)GsiDgrmGetSendMad(pCEPEntry->pDgrmElement),
|
|
Packit |
857059 |
CM_REJECT_REQUEST,
|
|
Packit |
857059 |
(uint16)pConnectReject->Reason,
|
|
Packit |
857059 |
&pConnectReject->RejectInfo[0],
|
|
Packit |
857059 |
pConnectReject->RejectInfoLen,
|
|
Packit |
857059 |
&pConnectReject->PrivateData[0],
|
|
Packit |
857059 |
CMM_REJ_USER_LEN,
|
|
Packit |
857059 |
pCEPEntry->TransactionID,
|
|
Packit |
857059 |
pCEPEntry->LocalCommID,
|
|
Packit |
857059 |
pCEPEntry->RemoteCommID);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Send out the REJ. We do not need to check the return since
|
|
Packit |
857059 |
// the other end will eventually timed-out if it does not received
|
|
Packit |
857059 |
// either RTU or REJ
|
|
Packit |
857059 |
Status = CmDgrmSend(pCEPEntry->pDgrmElement);
|
|
Packit |
857059 |
if (FSUCCESS != Status)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// fall through and let timer retry the send later
|
|
Packit |
857059 |
_DBG_WARN(("<cep 0x%p> DgrmSend() failed for REJ!!! <%s>\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
Status = FSUCCESS;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
AtomicIncrementVoid(&gCM->Sent.RejReq);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> REJ sent, rejecting REQ <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x reason %d>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEPEntry), pCEPEntry->LocalCommID, pCEPEntry->RemoteCommID,
|
|
Packit |
857059 |
pCEPEntry->PrimaryPath.LocalLID, pCEPEntry->PrimaryPath.RemoteLID,
|
|
Packit |
857059 |
pConnectReject->Reason));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Move from PENDING to INIT list
|
|
Packit |
857059 |
CepRemoveFromPendingList(pCEPEntry);
|
|
Packit |
857059 |
CepToIdle(pCEPEntry);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (bPeer)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// For peer request, the user created the obj
|
|
Packit |
857059 |
ASSERT(pCEPEntry == pCEP);
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
// This is the one we created when a new connection request arrived
|
|
Packit |
857059 |
DestroyCEP(pCEPEntry);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// If another connection is pending for this server endpoint,
|
|
Packit |
857059 |
// we must set it again to wake up the Wait()
|
|
Packit |
857059 |
if (pCEP->PendingCount)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
SetNotification(pCEP, CME_RCVD_REQ);//EventSet(pCEP, CME_RCVD_REQ);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
// TBD case CMS_REP_SENT: - allow and move to TimeWait, see Cancel
|
|
Packit |
857059 |
// TBD case CMS_MRA_REP_RCVD: - allow and move to TimeWait, see Cancel
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // switch()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // RejectP()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// CancelP
|
|
Packit |
857059 |
// CmCancel, DestroyCEP or remove CA while connecting
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Cancel processing of a passive side connection
|
|
Packit |
857059 |
// all local information is dropped, remote end is left to timeout
|
|
Packit |
857059 |
// user will get a FCM_CONNECT_CANCEL callback at which point user
|
|
Packit |
857059 |
// should destroy the now-idle CEP
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// In general this should be used only to cancel listeners.
|
|
Packit |
857059 |
// Internally it is used to do a quick cleanup for a Destroyed CEP
|
|
Packit |
857059 |
// or the removal of a CA, hence it does not attempt to send a Reject
|
|
Packit |
857059 |
// Applications should generally use CmReject instead of this to
|
|
Packit |
857059 |
// properly reject connections.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
CancelP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status=FPENDING;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
CM_CEP_OBJECT* pCEPEntry=NULL;
|
|
Packit |
857059 |
DLIST_ENTRY* pListEntry=NULL;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
switch (pCEP->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_LISTEN:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Cancel the listen request
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Clear the pending signal from the event obj since a REQ may be pending
|
|
Packit |
857059 |
// but before the signal is waited on
|
|
Packit |
857059 |
//CmEventReset(pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//BitSet(pCEP->EventFlags, USRE_CANCEL);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Clear the pending list
|
|
Packit |
857059 |
while (!DListIsEmpty(&pCEP->PendingList))
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
pListEntry = DListGetNext(&pCEP->PendingList);
|
|
Packit |
857059 |
pCEPEntry = PARENT_STRUCT(pListEntry, CM_CEP_OBJECT, PendingListEntry);
|
|
Packit |
857059 |
// Move from PENDING to INIT list and destroy it
|
|
Packit |
857059 |
ASSERT(pCEPEntry->pParentCEP == pCEP);
|
|
Packit |
857059 |
CepRemoveFromPendingList(pCEPEntry);
|
|
Packit |
857059 |
CepToIdle(pCEPEntry);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// This will start the timer in timewait state
|
|
Packit |
857059 |
DestroyCEP(pCEPEntry);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
ASSERT(pCEP->PendingCount == 0);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Move from LISTEN to IDLE
|
|
Packit |
857059 |
CM_MapRemoveEntry(&gCM->ListenMap, &pCEP->MapEntry, LISTEN_LIST, pCEP);
|
|
Packit |
857059 |
// ClearEndPoint in CepToIdle is benign
|
|
Packit |
857059 |
CepToIdle(pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Set the cancel event
|
|
Packit |
857059 |
SetNotification(pCEP, USRE_CANCEL);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// This tells us that a callback is pending or we are in the callback
|
|
Packit |
857059 |
//if (AtomicRead(&pCEP->CallbackRefCnt))
|
|
Packit |
857059 |
// Status = FPENDING;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case CMS_REQ_RCVD:
|
|
Packit |
857059 |
case CMS_MRA_REQ_SENT:
|
|
Packit |
857059 |
// Internal use, removed CA or cancelling listening CEP
|
|
Packit |
857059 |
ASSERT(!pCEP->bPeer || (pCEP->LocalEndPoint.QPN || pCEP->LocalEndPoint.EECN));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#if 0
|
|
Packit |
857059 |
// TBD - call RejectP, will end up in Idle
|
|
Packit |
857059 |
#else
|
|
Packit |
857059 |
// Move from PENDING to IDLE
|
|
Packit |
857059 |
CepRemoveFromPendingList(pCEP);
|
|
Packit |
857059 |
CepToIdle(pCEP);
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Set the cancel event
|
|
Packit |
857059 |
SetNotification(pCEP, USRE_CANCEL);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case CMS_REP_SENT:
|
|
Packit |
857059 |
case CMS_MRA_REP_RCVD:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Cancel the connection while waiting for the RTU to arrive.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Cancel the timer for REP msg
|
|
Packit |
857059 |
CmTimerStop(pCEP, REP_TIMER);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Clear the pending signal from the event obj since a RTU may be pending
|
|
Packit |
857059 |
// but before the signal is waited on
|
|
Packit |
857059 |
//CmEventReset(pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//BitSet(pCEP->EventFlags, USRE_CANCEL);
|
|
Packit |
857059 |
#if 0
|
|
Packit |
857059 |
// TBD - we should do this
|
|
Packit |
857059 |
send a REJ (timeout or similar) - use RejectP
|
|
Packit |
857059 |
CepToTimewait(pCEP)
|
|
Packit |
857059 |
// if user wants a FCM_DISCONNECTED at end of timewait, lets not confuse
|
|
Packit |
857059 |
// them with a FCM_CONNECT_CANCEL callback before it
|
|
Packit |
857059 |
if (! pCEP->bTimewaitCallback)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
if (pCEP->bAsyncAccept)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
SetNotification(pCEP, USRE_CANCEL); // callback
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
EventSet(pCEP, USRE_CANCEL, FALSE); // wakeup CmAccept wait
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
#else
|
|
Packit |
857059 |
CepToIdle(pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pCEP->bAsyncAccept)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
SetNotification(pCEP, USRE_CANCEL); // callback
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
EventSet(pCEP, USRE_CANCEL, FALSE); // wakeup CmAccept wait
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
// This tells us that a callback is pending or we are in the callback
|
|
Packit |
857059 |
//if (AtomicRead(&pCEP->CallbackRefCnt))
|
|
Packit |
857059 |
// Status = FPENDING;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//if (BitTest(pCEP->EventFlags, USRE_WAIT))
|
|
Packit |
857059 |
//{
|
|
Packit |
857059 |
// Status = FPENDING;
|
|
Packit |
857059 |
//}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//EventSet(pCEP, USRE_CANCEL);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case CMS_SIDR_REQ_RCVD:
|
|
Packit |
857059 |
// Move from PENDING to INIT list
|
|
Packit |
857059 |
CepRemoveFromPendingList(pCEP);
|
|
Packit |
857059 |
// ClearEndPoint in CepToIdle is benign
|
|
Packit |
857059 |
CepToIdle(pCEP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Set the cancel event - this CEP not user visible, so no callback
|
|
Packit |
857059 |
EventSet(pCEP, USRE_CANCEL, FALSE);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // switch()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // CancelP()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// build QP Attributes to load new alternate path into QP
|
|
Packit |
857059 |
// and prepare a Reply
|
|
Packit |
857059 |
FSTATUS ProcessAltPathRequestP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN CM_ALTPATH_INFO* AltPathRequest,
|
|
Packit |
857059 |
OUT CM_PROCESS_ALTPATH_REQUEST_INFO* Info
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status=FSUCCESS;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessAltPathRequestP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
|
|
Packit |
857059 |
switch (pCEP->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_LAP_RCVD:
|
|
Packit |
857059 |
case CMS_MRA_LAP_SENT:
|
|
Packit |
857059 |
MemoryClear(Info, sizeof(*Info)); // just to be safe
|
|
Packit |
857059 |
Info->QpAttrRts.RequestState = QPStateReadyToSend;
|
|
Packit |
857059 |
Info->QpAttrRts.APMState = APMStateRearm;
|
|
Packit |
857059 |
GetAVFromPath2(0, &AltPathRequest->AlternatePathInfo.Path, NULL,
|
|
Packit |
857059 |
&Info->QpAttrRts.AltDestAV);
|
|
Packit |
857059 |
Info->QpAttrRts.AltDestAV.PortGUID = pCEP->TempAlternateLocalPortGuid;
|
|
Packit |
857059 |
Info->QpAttrRts.AltDestAV.GlobalRouteInfo.SrcGIDIndex =
|
|
Packit |
857059 |
pCEP->TempAlternateLocalGidIndex;
|
|
Packit |
857059 |
Info->QpAttrRts.AltDestAV.PathBits = pCEP->TempAlternateLocalPathBits;
|
|
Packit |
857059 |
Info->QpAttrRts.AltPortGUID = pCEP->TempAlternateLocalPortGuid;
|
|
Packit |
857059 |
Info->QpAttrRts.AltPkeyIndex = pCEP->TempAlternatePkeyIndex;
|
|
Packit |
857059 |
Info->QpAttrRts.Attrs = IB_QP_ATTR_APMSTATE
|
|
Packit |
857059 |
|IB_QP_ATTR_ALTDESTAV|IB_QP_ATTR_ALTPORTGUID
|
|
Packit |
857059 |
| IB_QP_ATTR_ALTPKEYINDEX;
|
|
Packit |
857059 |
if (pCEP->Type != CM_UC_TYPE) {
|
|
Packit |
857059 |
Info->QpAttrRts.AltLocalAckTimeout = AltPathRequest->AlternateAckTimeout;
|
|
Packit |
857059 |
Info->QpAttrRts.Attrs |= IB_QP_ATTR_ALTLOCALACKTIMEOUT;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
Info->AltPathReply.APStatus = APS_PATH_LOADED;
|
|
Packit |
857059 |
// caller must iba_modify_qp(...) then iba_altpath_reply
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//////////////////////////////////////////////////////////////////////////
|
|
Packit |
857059 |
// AltPathReplyP
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Reply to an alternate path request
|
|
Packit |
857059 |
// Only allowed for Server/Passive side of connection
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// INPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// OUTPUTS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// None.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// RETURNS:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// FSUCCESS - APR queued to be sent.
|
|
Packit |
857059 |
// FINVALID_STATE - The endpoint is not in the valid state for this call
|
|
Packit |
857059 |
// FERROR - Unable to send the apr packet
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// IRQL:
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This routine is called at IRQL_PASSIVE_LEVEL.
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
AltPathReplyP(
|
|
Packit |
857059 |
IN CM_CEP_OBJECT* pCEP,
|
|
Packit |
857059 |
IN CM_ALTPATH_REPLY_INFO* pAprInfo // Send APR
|
|
Packit |
857059 |
)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status;
|
|
Packit |
857059 |
CM_MAD* pMad = NULL;
|
|
Packit |
857059 |
//uint64 elapsed_us=0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, AltPathReplyP);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ASSERT(pCEP->Mode == CM_MODE_PASSIVE);
|
|
Packit |
857059 |
switch (pCEP->State)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case CMS_LAP_RCVD:
|
|
Packit |
857059 |
case CMS_MRA_LAP_SENT:
|
|
Packit |
857059 |
pMad = (CM_MAD*)GsiDgrmGetSendMad(pCEP->pDgrmElement);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (pAprInfo->APStatus == APS_PATH_LOADED)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// still have the LAP we received, now we have
|
|
Packit |
857059 |
// accepted it as our alternate path
|
|
Packit |
857059 |
ASSERT(pMad->common.AttributeID == MCLASS_ATTRIB_ID_LAP);
|
|
Packit |
857059 |
CopyRcvdLAPToAltPath(&pMad->payload.LAP, &pCEP->AlternatePath);
|
|
Packit |
857059 |
pCEP->AlternatePath.LocalPortGuid = pCEP->TempAlternateLocalPortGuid;
|
|
Packit |
857059 |
pCEP->AlternatePath.LocalGidIndex = pCEP->TempAlternateLocalGidIndex;
|
|
Packit |
857059 |
pCEP->AlternatePath.LocalPathBits = pCEP->TempAlternateLocalPathBits;
|
|
Packit |
857059 |
pCEP->AlternatePath.PkeyIndex = pCEP->TempAlternatePkeyIndex;
|
|
Packit |
857059 |
} else if (pAprInfo->APStatus == APS_UNSUPPORTED_REQ) {
|
|
Packit |
857059 |
// in future no need to notify CEP of LAPs, it doesn't do APM
|
|
Packit |
857059 |
pCEP->bFailoverSupported = FALSE;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Update the turnaround time
|
|
Packit |
857059 |
// uncomment the 3 lines below to have LAP/APR response count toward
|
|
Packit |
857059 |
// average turnaround time
|
|
Packit |
857059 |
//elapsed_us = CmGetElapsedTime(pCEPEntry);
|
|
Packit |
857059 |
//gCM->turnaround_time_us = UpdateTurnaroundTime(gCM->turnaround_time_us, elapsed_us);
|
|
Packit |
857059 |
//_DBG_INFO(("Update turnaround time <tat %"PRIu64"us>.\n", gCM->turnaround_time_us));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
FormatAPR(pMad, (CM_APR_STATUS) pAprInfo->APStatus,
|
|
Packit |
857059 |
pAprInfo->u.AddInfo.Info,
|
|
Packit |
857059 |
pAprInfo->u.AddInfo.Len,
|
|
Packit |
857059 |
pAprInfo->PrivateData,
|
|
Packit |
857059 |
CM_APR_INFO_USER_LEN,
|
|
Packit |
857059 |
pCEP->TransactionID,
|
|
Packit |
857059 |
pCEP->LocalCommID,
|
|
Packit |
857059 |
pCEP->RemoteCommID);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// Send out the APR
|
|
Packit |
857059 |
Status = CmDgrmSend(pCEP->pDgrmElement);
|
|
Packit |
857059 |
if (FSUCCESS != Status)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// fall through and let timer retry the send later
|
|
Packit |
857059 |
_DBG_WARN(("<cep 0x%p> DgrmSend() failed for APR!!! <%s>\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), _DBG_PTR(FSTATUS_MSG(Status))));
|
|
Packit |
857059 |
Status = FSUCCESS;
|
|
Packit |
857059 |
} else {
|
|
Packit |
857059 |
if (pAprInfo->APStatus == APS_PATH_LOADED)
|
|
Packit |
857059 |
AtomicIncrementVoid(&gCM->Sent.AprAcc);
|
|
Packit |
857059 |
else
|
|
Packit |
857059 |
AtomicIncrementVoid(&gCM->Sent.AprRej);
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_INFO(("<cep 0x%p> APR sent <lcid 0x%x rcid 0x%x slid 0x%x dlid 0x%x>.\n",
|
|
Packit |
857059 |
_DBG_PTR(pCEP), pCEP->LocalCommID, pCEP->RemoteCommID,
|
|
Packit |
857059 |
pCEP->PrimaryPath.LocalLID, pCEP->PrimaryPath.RemoteLID));
|
|
Packit |
857059 |
|
|
Packit |
857059 |
CepSetState(pCEP, CMS_ESTABLISHED);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
Status = FINVALID_STATE;
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL(_DBG_LVL_FUNC_TRACE);
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
} // AltPathReplyP()
|
|
Packit |
857059 |
|
|
Packit |
857059 |
// EOF
|