Blame opamgt/src/opamgt_sa_notice.c

Packit 857059
/* BEGIN_ICS_COPYRIGHT2 ****************************************
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_COPYRIGHT2   ****************************************/
Packit 857059
Packit 857059
/* [ICS VERSION STRING: unknown] */
Packit 857059
Packit 857059
#include <poll.h>
Packit 857059
#include <errno.h>
Packit 857059
#include <string.h> /* strerror() */
Packit 857059
Packit 857059
Packit 857059
#define OPAMGT_PRIVATE 1
Packit 857059
#include "ib_utils_openib.h"
Packit 857059
#include "opamgt_dump_mad.h"
Packit 857059
#include "omgt_oob_net.h"
Packit 857059
#include "omgt_oob_protocol.h"
Packit 857059
Packit 857059
#include <opamgt.h>
Packit 857059
#include <opamgt_sa.h>
Packit 857059
#include <opamgt_sa_notice.h>
Packit 857059
#include <iba/stl_sa_priv.h>
Packit 857059
Packit 857059
Packit 857059
/**===========================================================================*/
Packit 857059
omgt_sa_registration_t* omgt_sa_find_reg(struct omgt_port *port, uint16_t trap_num)
Packit 857059
{
Packit 857059
	omgt_sa_registration_t *curr = port->regs_list;
Packit 857059
	while (curr != NULL) {
Packit 857059
		if (curr->trap_num == trap_num) {
Packit 857059
			return curr;
Packit 857059
		}
Packit 857059
		curr = curr->next;
Packit 857059
	}
Packit 857059
	return NULL;
Packit 857059
}
Packit 857059
/**===========================================================================*/
Packit 857059
OMGT_STATUS_T omgt_sa_register_trap(struct omgt_port *port, uint16_t trap_num,
Packit 857059
	void *context)
Packit 857059
{
Packit 857059
	OMGT_STATUS_T status;
Packit 857059
	int ret;
Packit 857059
	omgt_sa_registration_t *reg;
Packit 857059
Packit 857059
	if (port->is_oob_enabled) {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, Trap registration not Supported\n");
Packit 857059
		return OMGT_STATUS_INVALID_STATE;
Packit 857059
	}
Packit 857059
Packit 857059
	reg = (omgt_sa_registration_t *)calloc(1, sizeof*reg);
Packit 857059
	if (reg == NULL) {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "failed to allocate reg structure\n");
Packit 857059
		return OMGT_STATUS_ERROR;
Packit 857059
	}
Packit 857059
Packit 857059
	status = FTIMEOUT;
Packit 857059
	if (omgt_lock_sem(&port->lock)) {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "failed to acquire lock (status: %d)\n", status);
Packit 857059
		free(reg);
Packit 857059
		return OMGT_STATUS_ERROR;
Packit 857059
	}
Packit 857059
Packit 857059
	if (omgt_sa_find_reg(port, trap_num)) {
Packit 857059
		omgt_unlock_sem(&port->lock);
Packit 857059
		free(reg);
Packit 857059
		return OMGT_STATUS_SUCCESS;
Packit 857059
	}
Packit 857059
Packit 857059
	if ((ret = create_sa_qp(port)) != 0) {
Packit 857059
		omgt_unlock_sem(&port->lock);
Packit 857059
		OMGT_OUTPUT_ERROR(port, "failed to create notice QP for trap (%u) registration (status: %d)\n",
Packit 857059
			trap_num, ret);
Packit 857059
	} else if ((ret = userspace_register(port, trap_num, reg)) != 0) {
Packit 857059
		omgt_unlock_sem(&port->lock);
Packit 857059
		OMGT_OUTPUT_ERROR(port, "failed to register for trap (%u) (status: %d)\n",
Packit 857059
			trap_num, ret);
Packit 857059
	}
Packit 857059
Packit 857059
	if (ret) {
Packit 857059
		free(reg);
Packit 857059
		return OMGT_STATUS_ERROR;
Packit 857059
	}
Packit 857059
Packit 857059
	reg->user_context = context;
Packit 857059
	reg->trap_num = trap_num;
Packit 857059
	omgt_sa_add_reg_unsafe(port, reg);
Packit 857059
Packit 857059
	omgt_unlock_sem(&port->lock);
Packit 857059
	return OMGT_STATUS_SUCCESS;
Packit 857059
}
Packit 857059
/**===========================================================================*/
Packit 857059
OMGT_STATUS_T omgt_sa_unregister_trap(struct omgt_port *port, uint16_t trap_num)
Packit 857059
{
Packit 857059
	OMGT_STATUS_T status;
Packit 857059
Packit 857059
	if (port->is_oob_enabled) {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "Port in Out-of-Band Mode, Trap (un)registration not Supported\n");
Packit 857059
		return OMGT_STATUS_INVALID_STATE;
Packit 857059
	}
Packit 857059
Packit 857059
	if (omgt_lock_sem(&port->lock))
Packit 857059
		return OMGT_STATUS_ERROR;
Packit 857059
Packit 857059
	status = omgt_sa_remove_reg_by_trap_unsafe(port, trap_num);
Packit 857059
Packit 857059
	omgt_unlock_sem(&port->lock);
Packit 857059
	return status;
Packit 857059
}
Packit 857059
/**===========================================================================*/
Packit 857059
OMGT_STATUS_T omgt_sa_get_notice_report(struct omgt_port *port, STL_NOTICE **notice,
Packit 857059
	size_t *notice_len, void **context, int poll_timeout_ms)
Packit 857059
{
Packit 857059
	int rc;
Packit 857059
	int bytes_read;
Packit 857059
	struct pollfd pollfd[1];
Packit 857059
	uint8_t rcv_buf[2048];
Packit 857059
	struct omgt_thread_msg *msg;
Packit 857059
	STL_NOTICE *notice_buf = NULL;
Packit 857059
	omgt_sa_registration_t *reg;
Packit 857059
	uint16_t trap_num;
Packit 857059
Packit 857059
	if (port->is_oob_enabled) {
Packit 857059
		uint32_t oob_recv_len = 0;
Packit 857059
		OOB_PACKET *packet = NULL;
Packit 857059
Packit 857059
		if (!port->is_oob_notice_setup) {
Packit 857059
			OMGT_STATUS_T status;
Packit 857059
			if ((status = omgt_oob_net_connect(port, &port->notice_conn)) != FSUCCESS) {
Packit 857059
				OMGT_OUTPUT_ERROR(port, "failed to establish a connection to the host: %u\n", status);
Packit 857059
				return status;
Packit 857059
			}
Packit 857059
			port->is_oob_notice_setup = TRUE;
Packit 857059
		}
Packit 857059
Packit 857059
		do {
Packit 857059
			/* Process IP 'blobs' (TCP Segments) */
Packit 857059
			omgt_oob_net_process(port, port->notice_conn, poll_timeout_ms, 1);
Packit 857059
			/* If failure return error */
Packit 857059
			if (port->notice_conn->err) {
Packit 857059
				return OMGT_STATUS_ERROR;
Packit 857059
			}
Packit 857059
		} while (port->notice_conn->blob_in_progress);
Packit 857059
Packit 857059
		/* Check if we are done getting all the 'blobs' */
Packit 857059
		omgt_oob_net_get_next_message(port->notice_conn, (uint8_t **)&packet, (int *)&oob_recv_len);
Packit 857059
		/* Handle Timeout Case */
Packit 857059
		if (packet == NULL) {
Packit 857059
			return OMGT_STATUS_TIMEOUT;
Packit 857059
		}
Packit 857059
Packit 857059
		/* Handle packet */
Packit 857059
		oob_recv_len = 0;
Packit 857059
		BSWAP_OOB_HEADER(&(packet->Header));
Packit 857059
		oob_recv_len = packet->Header.Length;
Packit 857059
		BSWAP_MAD_HEADER((MAD *)&packet->MadData.common);
Packit 857059
Packit 857059
		/* Handle Trap/Notice Report */
Packit 857059
		if (packet->MadData.common.AttributeID == STL_MCLASS_ATTRIB_ID_NOTICE) {
Packit 857059
			/* Remove Header Bytes */
Packit 857059
			oob_recv_len -= (sizeof(MAD_COMMON) - sizeof(RMPP_HEADER) - sizeof(SA_HDR));
Packit 857059
Packit 857059
			/* Allocate the Notice */
Packit 857059
			notice_buf = (STL_NOTICE *)calloc(1, oob_recv_len);
Packit 857059
			if (notice_buf == NULL) {
Packit 857059
				OMGT_OUTPUT_ERROR(port, "failed to allocate notice buffer\n");
Packit 857059
				return OMGT_STATUS_INSUFFICIENT_MEMORY;
Packit 857059
			}
Packit 857059
Packit 857059
			/* Copy and allocate the Data */
Packit 857059
			SA_MAD *samad = (SA_MAD *)&packet->MadData.common;
Packit 857059
			memcpy(notice_buf, samad->Data, oob_recv_len);
Packit 857059
			BSWAP_STL_NOTICE(notice_buf);
Packit 857059
			trap_num = notice_buf->Attributes.Generic.TrapNumber;
Packit 857059
			OMGT_DBGPRINT(port, "trap message %u: %d bytes\n", trap_num, oob_recv_len);
Packit 857059
Packit 857059
			/* Find Context (Not in OOB) */
Packit 857059
			if (context) {
Packit 857059
				*context = NULL;
Packit 857059
			}
Packit 857059
			/* Set Notice struct and length */
Packit 857059
			*notice = notice_buf;
Packit 857059
			*notice_len = oob_recv_len;
Packit 857059
			return OMGT_STATUS_SUCCESS;
Packit 857059
		/* Handle Inform Info */
Packit 857059
		} else if (packet->MadData.common.AttributeID == STL_MCLASS_ATTRIB_ID_INFORM_INFO) {
Packit 857059
			SA_MAD *samad = (SA_MAD *)&packet->MadData.common;
Packit 857059
			STL_INFORM_INFO *informinfo = (STL_INFORM_INFO *)samad->Data;
Packit 857059
			trap_num = ntoh16(informinfo->u.Generic.TrapNumber);
Packit 857059
Packit 857059
			/* Free Packet */
Packit 857059
			free(packet);
Packit 857059
Packit 857059
			OMGT_OUTPUT_ERROR(port, "Registration of Trap message timed out: Trap %u\n", trap_num);
Packit 857059
			return OMGT_STATUS_DISCONNECT;
Packit 857059
		/* Otherwise error */
Packit 857059
		} else {
Packit 857059
			SA_MAD *samad = (SA_MAD *)&packet->MadData.common;
Packit 857059
			OMGT_OUTPUT_ERROR(port, "Unexpected OOB MAD recieved: %s %s(%s)\n",
Packit 857059
				stl_class_str(samad->common.BaseVersion, samad->common.MgmtClass),
Packit 857059
				stl_method_str(samad->common.BaseVersion, samad->common.MgmtClass, samad->common.mr.AsReg8),
Packit 857059
				stl_attribute_str(samad->common.BaseVersion, samad->common.MgmtClass, hton16(samad->common.AttributeID)));
Packit 857059
Packit 857059
			/* Free Packet */
Packit 857059
			free(packet);
Packit 857059
			return OMGT_STATUS_ERROR;
Packit 857059
		}
Packit 857059
	}
Packit 857059
	pollfd[0].fd = port->umad_port_sv[0];
Packit 857059
	pollfd[0].events = POLLIN;
Packit 857059
	pollfd[0].revents = 0;
Packit 857059
Packit 857059
	/* Poll for event */
Packit 857059
	if ((rc = poll(pollfd, 1, poll_timeout_ms)) < 0) {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "trap poll failed : %s\n", strerror(errno));
Packit 857059
		return FERROR;
Packit 857059
Packit 857059
	} else if (rc == 0) {
Packit 857059
		/* Handle Timeout Case */
Packit 857059
		return OMGT_STATUS_TIMEOUT;
Packit 857059
	} else if (pollfd[0].revents & POLLIN) {
Packit 857059
		/* Read from Stream */
Packit 857059
		bytes_read = read(port->umad_port_sv[0], rcv_buf, sizeof(rcv_buf));
Packit 857059
		if (bytes_read <= 0) {
Packit 857059
			OMGT_OUTPUT_ERROR(port, "user event read failed : %s\n", strerror(errno));
Packit 857059
			return OMGT_STATUS_ERROR;
Packit 857059
		}
Packit 857059
Packit 857059
		/* Determine Message Type */
Packit 857059
		msg = (struct omgt_thread_msg *)rcv_buf;
Packit 857059
		if (OMGT_TH_EVT_TRAP_MSG == msg->evt) {
Packit 857059
			int bufSize = MIN(msg->size,sizeof(rcv_buf)-sizeof(*msg));
Packit 857059
			/* Thread Event Type : Trap Message */
Packit 857059
Packit 857059
			/* Allocate the Notice */
Packit 857059
			notice_buf = (STL_NOTICE *)calloc(1, bufSize);
Packit 857059
			if (notice_buf == NULL) {
Packit 857059
				OMGT_OUTPUT_ERROR(port, "failed to allocate notice buffer\n");
Packit 857059
				return OMGT_STATUS_INSUFFICIENT_MEMORY;
Packit 857059
			}
Packit 857059
			/* Copy and allocate the Data */
Packit 857059
			memcpy(notice_buf, rcv_buf + sizeof(*msg), bufSize);
Packit 857059
			BSWAP_STL_NOTICE(notice_buf);
Packit 857059
			trap_num = notice_buf->Attributes.Generic.TrapNumber;
Packit 857059
			OMGT_DBGPRINT(port, "trap message %u: %d bytes\n", trap_num, (int)(msg->size));
Packit 857059
Packit 857059
			/* Find Context */
Packit 857059
			if (context) {
Packit 857059
				reg = omgt_sa_find_reg(port, trap_num);
Packit 857059
				if (reg == NULL) {
Packit 857059
					OMGT_OUTPUT_ERROR(port, "failed to retrieve registration: trap %u\n", trap_num);
Packit 857059
					*context = NULL;
Packit 857059
				} else {
Packit 857059
					/* Set context */
Packit 857059
					*context = reg->user_context;
Packit 857059
				}
Packit 857059
			}
Packit 857059
Packit 857059
			/* Set Notice struct and length */
Packit 857059
			*notice = notice_buf;
Packit 857059
			*notice_len = msg->size;
Packit 857059
			return OMGT_STATUS_SUCCESS;
Packit 857059
Packit 857059
		} else if (OMGT_TH_EVT_TRAP_REG_ERR_TIMEOUT == msg->evt) {
Packit 857059
			/* Thread Event Type : Registration Timeout */
Packit 857059
			STL_INFORM_INFO *informinfo = (STL_INFORM_INFO *)msg->data;
Packit 857059
			trap_num = ntoh16(informinfo->u.Generic.TrapNumber);
Packit 857059
			OMGT_OUTPUT_ERROR(port, "Registration of Trap message timed out: Trap %u\n", trap_num);
Packit 857059
Packit 857059
			return OMGT_STATUS_DISCONNECT;
Packit 857059
		} else {
Packit 857059
			OMGT_OUTPUT_ERROR(port, "user event read invalid message: %u\n", msg->evt);
Packit 857059
			return OMGT_STATUS_ERROR;
Packit 857059
		}
Packit 857059
	} else {
Packit 857059
		OMGT_OUTPUT_ERROR(port, "trap poll unexpected result : %d\n", pollfd[0].revents);
Packit 857059
		return OMGT_STATUS_ERROR;
Packit 857059
	}
Packit 857059
	return OMGT_STATUS_SUCCESS;
Packit 857059
}