Blame IbAccess/Common/SubnetDriver/report.c

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
}