|
Packit |
857059 |
/* BEGIN_ICS_COPYRIGHT2 ****************************************
|
|
Packit |
857059 |
|
|
Packit Service |
3f7ca0 |
Copyright (c) 2015-2020, 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 Service |
3f7ca0 |
OMGT_OUTPUT_ERROR(port, "Unexpected OOB MAD received: %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 |
}
|