|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT4 ****************************************
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Copyright (c) 2015-2017, 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 |
|
|
Packit |
857059 |
\file report.h
|
|
Packit |
857059 |
|
|
Packit |
857059 |
$Revision$
|
|
Packit |
857059 |
$Date$
|
|
Packit |
857059 |
|
|
Packit |
857059 |
\brief Routines to handle reports for trap events
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
|
|
Packit |
857059 |
#include <report.h>
|
|
Packit |
857059 |
#include <subscribe.h>
|
|
Packit |
857059 |
#include <sdi.h>
|
|
Packit |
857059 |
#include "iba/stl_mad_priv.h"
|
|
Packit |
857059 |
#include <imap.h>
|
|
Packit |
857059 |
#include <imemory.h>
|
|
Packit |
857059 |
#include <dbg.h>
|
|
Packit |
857059 |
#include <ib_debug.h>
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*!
|
|
Packit |
857059 |
\brief Sends a ReportResponse message to the SM acknowledging we have received
|
|
Packit |
857059 |
the report message. This should stop the SM from send us the report again.
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
static __inline
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
SendReportResponse(void *pContext, IBT_DGRM_ELEMENT *pReportDgrmList)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status;
|
|
Packit |
857059 |
uint32 ElementCount;
|
|
Packit |
857059 |
IBT_DGRM_ELEMENT *pResponseDgrmElement;
|
|
Packit |
857059 |
MAD *pReportMad;
|
|
Packit |
857059 |
MAD *pResponseMad;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, SendReportResponse);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Get a datagram element from the SA datagram pool
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
ElementCount = 1;
|
|
Packit |
857059 |
Status = iba_gsi_dgrm_pool_get( sa_represp_poolhandle, &ElementCount, &pResponseDgrmElement );
|
|
Packit |
857059 |
#ifdef SA_ALLOC_DEBUG
|
|
Packit |
857059 |
if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("get sa for report: Status %d\n", Status);
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
if ( Status != FSUCCESS )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_ERROR( ( "Failed to get DGRM Element. Status 0x%x\n", Status ) );
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pResponseDgrmElement->Element.pContext = pContext;
|
|
Packit |
857059 |
pResponseDgrmElement->RemoteQP = pReportDgrmList->RemoteQP;
|
|
Packit |
857059 |
pResponseDgrmElement->RemoteQKey = pReportDgrmList->RemoteQKey;
|
|
Packit |
857059 |
pResponseDgrmElement->RemoteLID = pReportDgrmList->RemoteLID;
|
|
Packit |
857059 |
pResponseDgrmElement->ServiceLevel = pReportDgrmList->ServiceLevel;
|
|
Packit |
857059 |
pResponseDgrmElement->PortGuid = pReportDgrmList->PortGuid;
|
|
Packit |
857059 |
pResponseDgrmElement->PathBits = pReportDgrmList->PathBits;
|
|
Packit |
857059 |
pResponseDgrmElement->StaticRate = pReportDgrmList->StaticRate;
|
|
Packit |
857059 |
pResponseDgrmElement->PkeyIndex = pReportDgrmList->PkeyIndex;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pReportMad = GsiDgrmGetRecvMad(pReportDgrmList);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pResponseMad = GsiDgrmGetSendMad(pResponseDgrmElement);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// Set various fields within MAD itself now
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
MemoryClear( pResponseMad, sizeof(MAD) );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pResponseMad->common.BaseVersion = IB_BASE_VERSION;
|
|
Packit |
857059 |
pResponseMad->common.MgmtClass = MCLASS_SUBN_ADM;
|
|
Packit |
857059 |
pResponseMad->common.ClassVersion = IB_SUBN_ADM_CLASS_VERSION;
|
|
Packit |
857059 |
pResponseMad->common.mr.AsReg8 = MMTHD_REPORT_RESP;
|
|
Packit |
857059 |
pResponseMad->common.u.NS.Status.AsReg16 = MAD_STATUS_SUCCESS;
|
|
Packit |
857059 |
pResponseMad->common.TransactionID = pReportMad->common.TransactionID;
|
|
Packit |
857059 |
pResponseMad->common.AttributeID = MCLASS_ATTRIB_ID_NOTICE;
|
|
Packit |
857059 |
pResponseMad->common.AttributeModifier = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pResponseDgrmElement->Element.pBufferList->ByteCount = sizeof(MAD_COMMON);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = iba_gsi_post_send( GsiSAHandle, pResponseDgrmElement );
|
|
Packit |
857059 |
#ifdef SA_ALLOC_DEBUG
|
|
Packit |
857059 |
if (iba_gsi_dgrm_pool_count(sa_poolhandle) < 50) MsgOut("send sa for report: Status %d\n", Status);
|
|
Packit |
857059 |
#endif
|
|
Packit |
857059 |
if ( Status != FSUCCESS )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
// This should not happen and if this happens it
|
|
Packit |
857059 |
//can be due to port status changinging to inactive
|
|
Packit |
857059 |
// Free the TSL DGRM Element
|
|
Packit |
857059 |
//
|
|
Packit |
857059 |
|
|
Packit |
857059 |
iba_gsi_dgrm_pool_put( pResponseDgrmElement );
|
|
Packit |
857059 |
_DBG_ERROR( ( "iba_gsi_post_send failed, Status = %d\n", Status ) );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
exit:
|
|
Packit |
857059 |
_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*!
|
|
Packit |
857059 |
\brief Validates that the fields in the report make sense
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
static __inline
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
ValidateReport(IBT_DGRM_ELEMENT *pReportDgrmList)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status = FSUCCESS;
|
|
Packit |
857059 |
SA_MAD *pReportMad = (SA_MAD *)GsiDgrmGetRecvMad(pReportDgrmList);
|
|
Packit |
857059 |
uint32 ByteCount = pReportDgrmList->Element.pBufferList->pNextBuffer->ByteCount;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ValidateReport);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( ByteCount < sizeof(SA_MAD) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_ERROR( ("Invalid ByteCount. Expected %d, Received %d\n",
|
|
Packit |
857059 |
(int)(sizeof(SA_MAD) + sizeof(IB_NOTICE)),
|
|
Packit |
857059 |
ByteCount) );
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( pReportDgrmList->Element.pNextElement != NULL )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Should be single element
|
|
Packit |
857059 |
_DBG_ERROR( ("Error Multi Element Request Received\n") );
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( pReportMad->common.AttributeID != MCLASS_ATTRIB_ID_NOTICE )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Should be a Notice Attribute ID
|
|
Packit |
857059 |
_DBG_ERROR( ("Invalid AttributeID. Expected %d, Received %d\n",
|
|
Packit |
857059 |
MCLASS_ATTRIB_ID_NOTICE,
|
|
Packit |
857059 |
pReportMad->common.AttributeID) );
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if ( !( pReportMad->common.AttributeModifier == 0 ) )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
// Attribute Modifier must be zero
|
|
Packit |
857059 |
_DBG_ERROR( ("Invalid AttributeModifier. Expected %d, Received %d\n",
|
|
Packit |
857059 |
0,
|
|
Packit |
857059 |
pReportMad->common.AttributeModifier) );
|
|
Packit |
857059 |
Status = FERROR;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
exit:
|
|
Packit |
857059 |
_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*!
|
|
Packit |
857059 |
\brief Swaps the Notice and the Notice Details data (based on trap) fields
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
static __inline
|
|
Packit |
857059 |
void
|
|
Packit |
857059 |
BSwapNoticeRecord(IB_NOTICE *pNotice, boolean toHostOrder)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
void *pNoticeDataDetails;
|
|
Packit |
857059 |
uint16 trapNumber = 0;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, BSwapNoticeRecord);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
if (! toHostOrder)
|
|
Packit |
857059 |
trapNumber = pNotice->u.Generic.TrapNumber;
|
|
Packit |
857059 |
BSWAP_IB_NOTICE(pNotice);
|
|
Packit |
857059 |
if (toHostOrder)
|
|
Packit |
857059 |
trapNumber = pNotice->u.Generic.TrapNumber;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
pNoticeDataDetails = pNotice->Data;
|
|
Packit |
857059 |
switch (trapNumber)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
case SMA_TRAP_GID_NOW_IN_SERVICE:
|
|
Packit |
857059 |
BSWAP_TRAP_64_DETAILS((TRAP_64_DETAILS *)pNoticeDataDetails);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case SMA_TRAP_GID_OUT_OF_SERVICE:
|
|
Packit |
857059 |
BSWAP_TRAP_65_DETAILS((TRAP_65_DETAILS *)pNoticeDataDetails);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case SMA_TRAP_ADD_MULTICAST_GROUP:
|
|
Packit |
857059 |
BSWAP_TRAP_66_DETAILS((TRAP_66_DETAILS *)pNoticeDataDetails);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
case SMA_TRAP_DEL_MULTICAST_GROUP:
|
|
Packit |
857059 |
BSWAP_TRAP_67_DETAILS((TRAP_67_DETAILS *)pNoticeDataDetails);
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
|
|
Packit |
857059 |
default:
|
|
Packit |
857059 |
break;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
/*!
|
|
Packit |
857059 |
\brief Performs the processing required to acknowledge, validate, adjust and inform clients
|
|
Packit |
857059 |
when a report message has been received from the Subnet Manager
|
|
Packit |
857059 |
*/
|
|
Packit |
857059 |
FSTATUS
|
|
Packit |
857059 |
ProcessReport( void *pContext, IBT_DGRM_ELEMENT *pReportDgrmList )
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
FSTATUS Status;
|
|
Packit |
857059 |
IB_NOTICE *pNotice = (IB_NOTICE *)(((SA_MAD *)GsiDgrmGetRecvMad(pReportDgrmList))->Data);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
_DBG_ENTER_LVL(_DBG_LVL_FUNC_TRACE, ProcessReport);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = SendReportResponse( pContext, pReportDgrmList );
|
|
Packit |
857059 |
if (Status != FSUCCESS)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_ERROR( ( "SendReportResponse failed, Status = %d\n", Status ) );
|
|
Packit |
857059 |
/* Continue on as report still could be valid */
|
|
Packit |
857059 |
Status = FSUCCESS;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
Status = ValidateReport( pReportDgrmList );
|
|
Packit |
857059 |
if (Status != FSUCCESS)
|
|
Packit |
857059 |
{
|
|
Packit |
857059 |
_DBG_ERROR( ( "ValidateReport failed, Status = %d\n", Status ) );
|
|
Packit |
857059 |
goto exit;
|
|
Packit |
857059 |
}
|
|
Packit |
857059 |
|
|
Packit |
857059 |
BSwapNoticeRecord(pNotice, TRUE);
|
|
Packit |
857059 |
|
|
Packit |
857059 |
ProcessClientTraps( pContext, pNotice, pReportDgrmList->PortGuid );
|
|
Packit |
857059 |
|
|
Packit |
857059 |
BSwapNoticeRecord(pNotice, FALSE);
|
|
Packit |
857059 |
exit:
|
|
Packit |
857059 |
_DBG_LEAVE_LVL( _DBG_LVL_FUNC_TRACE );
|
|
Packit |
857059 |
return Status;
|
|
Packit |
857059 |
}
|