Beispiel #1
0
static void vl15_send_mad(osm_vl15_t * p_vl, osm_madw_t * p_madw)
{
	ib_api_status_t status;
	boolean_t resp_expected = p_madw->resp_expected;

	/*
	   Non-response-expected mads are not throttled on the wire
	   since we can have no confirmation that they arrived
	   at their destination.
	 */
	if (resp_expected)
		/*
		   Note that other threads may not see the response MAD
		   arrive before send() even returns.
		   In that case, the wire count would temporarily go negative.
		   To avoid this confusion, preincrement the counts on the
		   assumption that send() will succeed.
		 */
		cl_atomic_inc(&p_vl->p_stats->qp0_mads_outstanding_on_wire);
	else
		cl_atomic_inc(&p_vl->p_stats->qp0_unicasts_sent);

	cl_atomic_inc(&p_vl->p_stats->qp0_mads_sent);

	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	if (status == IB_SUCCESS) {
		OSM_LOG(p_vl->p_log, OSM_LOG_DEBUG,
			"%u QP0 MADs on wire, %u outstanding, "
			"%u unicasts sent, %u total sent\n",
			p_vl->p_stats->qp0_mads_outstanding_on_wire,
			p_vl->p_stats->qp0_mads_outstanding,
			p_vl->p_stats->qp0_unicasts_sent,
			p_vl->p_stats->qp0_mads_sent);
		return;
	}

	OSM_LOG(p_vl->p_log, OSM_LOG_ERROR, "ERR 3E03: "
		"MAD send failed (%s)\n", ib_get_err_str(status));

	/*
	   The MAD was never successfully sent, so
	   fix up the pre-incremented count values.
	 */

	/* Decrement qp0_mads_sent that were incremented in the code above.
	   qp0_mads_outstanding will be decremented by send error callback
	   (called by osm_vendor_send() */
	cl_atomic_dec(&p_vl->p_stats->qp0_mads_sent);
	if (!resp_expected)
		cl_atomic_dec(&p_vl->p_stats->qp0_unicasts_sent);
}
/****f* opensm: SM/__osm_sm_mad_ctrl_process_set
 * NAME
 * __osm_sm_mad_ctrl_process_set
 *
 * DESCRIPTION
 * This function handles method Set() for received MADs.
 *
 * SYNOPSIS
 */
static void
__osm_sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * const p_ctrl,
			      IN osm_madw_t * p_madw)
{
	ib_smp_t *p_smp;
	cl_status_t status;
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;

	OSM_LOG_ENTER(p_ctrl->p_log);

	p_smp = osm_madw_get_smp_ptr(p_madw);

	/*
	   Note that attr_id (like the rest of the MAD) is in
	   network byte order.
	 */
	switch (p_smp->attr_id) {
	case IB_MAD_ATTR_SM_INFO:
		msg_id = OSM_MSG_MAD_SM_INFO;
		break;

	default:
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: "
			"Unsupported attribute = 0x%X\n",
			cl_ntoh16(p_smp->attr_id));
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
		break;
	}

	if (msg_id == CL_DISP_MSGID_NONE) {
		/*
		   There is an unknown MAD attribute type for which there is
		   no recipient.  Simply retire the MAD here.
		 */
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
		goto Exit;
	}

	/*
	   Post this MAD to the dispatcher for asynchronous
	   processing by the appropriate controller.
	 */

	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
		osm_get_disp_msg_str(msg_id));

	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);

	if (status != CL_SUCCESS) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: "
			"Dispatcher post message failed (%s)\n",
			CL_STATUS_MSG(status));
		goto Exit;
	}

Exit:
	OSM_LOG_EXIT(p_ctrl->p_log);
}
Beispiel #3
0
osm_madw_t *osm_mad_pool_get_wrapper(IN osm_mad_pool_t * const p_pool,
                                     IN osm_bind_handle_t h_bind,
                                     IN const uint32_t total_size,
                                     IN const ib_mad_t * const p_mad,
                                     IN const osm_mad_addr_t * const p_mad_addr)
{
    osm_madw_t *p_madw;

    CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
    CL_ASSERT(total_size);
    CL_ASSERT(p_mad);

    /*
       First, acquire a mad wrapper from the mad wrapper pool.
     */
    p_madw = malloc(sizeof(*p_madw));
    if (p_madw == NULL)
        goto Exit;

    /*
       Finally, initialize the wrapper object.
     */
    cl_atomic_inc(&p_pool->mads_out);
    osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);
    osm_madw_set_mad(p_madw, p_mad);

Exit:
    return (p_madw);
}
Beispiel #4
0
osm_madw_t *osm_mad_pool_get_wrapper_raw(IN osm_mad_pool_t * const p_pool)
{
    osm_madw_t *p_madw;

    p_madw = malloc(sizeof(*p_madw));
    if (!p_madw)
        return NULL;

    osm_madw_init(p_madw, 0, 0, 0);
    osm_madw_set_mad(p_madw, 0);
    cl_atomic_inc(&p_pool->mads_out);

    return (p_madw);
}
Beispiel #5
0
ib_api_status_t osm_sa_send(osm_sa_t *sa, IN osm_madw_t * p_madw,
			    IN boolean_t resp_expected)
{
	ib_api_status_t status;

	cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent);
	status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected);
	if (status != IB_SUCCESS) {
		cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent);
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: "
			"osm_vendor_send failed, status = %s\n",
			ib_get_err_str(status));
	}
	return status;
}
Beispiel #6
0
osm_madw_t *osm_mad_pool_get(IN osm_mad_pool_t * const p_pool,
                             IN osm_bind_handle_t h_bind,
                             IN const uint32_t total_size,
                             IN const osm_mad_addr_t * const p_mad_addr)
{
    osm_madw_t *p_madw;
    ib_mad_t *p_mad;

    CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);
    CL_ASSERT(total_size);

    /*
       First, acquire a mad wrapper from the mad wrapper pool.
     */
    p_madw = malloc(sizeof(*p_madw));
    if (p_madw == NULL)
        goto Exit;

    osm_madw_init(p_madw, h_bind, total_size, p_mad_addr);

    /*
       Next, acquire a wire mad of the specified size.
     */
    p_mad = osm_vendor_get(h_bind, total_size, &p_madw->vend_wrap);
    if (p_mad == NULL) {
        /* Don't leak wrappers! */
        free(p_madw);
        p_madw = NULL;
        goto Exit;
    }

    cl_atomic_inc(&p_pool->mads_out);
    /*
       Finally, attach the wire MAD to this wrapper.
     */
    osm_madw_set_mad(p_madw, p_mad);

Exit:
    return p_madw;
}
/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback
 * NAME
 * __osm_sm_mad_ctrl_rcv_callback
 *
 * DESCRIPTION
 * This is the callback from the transport layer for received MADs.
 *
 * SYNOPSIS
 */
static void
__osm_sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw,
			       IN void *bind_context,
			       IN osm_madw_t * p_req_madw)
{
	osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context;
	ib_smp_t *p_smp;
	ib_net16_t status;

	OSM_LOG_ENTER(p_ctrl->p_log);

	CL_ASSERT(p_madw);

	/*
	   A MAD was received from the wire, possibly in response to a request.
	 */
	cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd);

	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n",
		p_ctrl->p_stats->qp0_mads_rcvd);

	p_smp = osm_madw_get_smp_ptr(p_madw);

	/* if we are closing down simply do nothing */
	if (osm_exit_flag) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR,
			"Ignoring received mad - since we are exiting\n");

		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_DEBUG);

		/* retire the mad or put it back */
		if (ib_smp_is_response(p_smp) ||
		    (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS)) {
			CL_ASSERT(p_madw->resp_expected == FALSE);
			__osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
		} else if (p_madw->resp_expected == TRUE)
			__osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);
		else
			osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);

		goto Exit;
	}

	if (osm_log_is_active(p_ctrl->p_log, OSM_LOG_FRAMES))
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_FRAMES);

	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR)
		status = ib_smp_get_status(p_smp);
	else
		status = p_smp->status;

	if (status != 0) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3111: "
			"Error status = 0x%X\n", status);
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
	}

	switch (p_smp->method) {
	case IB_MAD_METHOD_GET_RESP:
		CL_ASSERT(p_req_madw != NULL);
		__osm_sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw);
		break;

	case IB_MAD_METHOD_GET:
		CL_ASSERT(p_req_madw == NULL);
		__osm_sm_mad_ctrl_process_get(p_ctrl, p_madw);
		break;

	case IB_MAD_METHOD_TRAP:
		CL_ASSERT(p_req_madw == NULL);
		__osm_sm_mad_ctrl_process_trap(p_ctrl, p_madw);
		break;

	case IB_MAD_METHOD_SET:
		CL_ASSERT(p_req_madw == NULL);
		__osm_sm_mad_ctrl_process_set(p_ctrl, p_madw);
		break;

	case IB_MAD_METHOD_SEND:
	case IB_MAD_METHOD_REPORT:
	case IB_MAD_METHOD_REPORT_RESP:
	case IB_MAD_METHOD_TRAP_REPRESS:
	default:
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: "
			"Unsupported method = 0x%X\n", p_smp->method);
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
		osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw);
		goto Exit;
	}

Exit:
	OSM_LOG_EXIT(p_ctrl->p_log);
}
/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp
 * NAME
 * __osm_sm_mad_ctrl_process_get_resp
 *
 * DESCRIPTION
 * This function handles method GetResp() for received MADs.
 * This is the most common path for QP0 MADs.
 *
 * SYNOPSIS
 */
static void
__osm_sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * const p_ctrl,
				   IN osm_madw_t * p_madw,
				   IN void *transaction_context)
{
	ib_smp_t *p_smp;
	cl_status_t status;
	osm_madw_t *p_old_madw;
	cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE;

	OSM_LOG_ENTER(p_ctrl->p_log);

	CL_ASSERT(p_madw);
	CL_ASSERT(transaction_context);

	p_smp = osm_madw_get_smp_ptr(p_madw);

	if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: "
			"'D' bit not set in returned SMP\n");
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
	}

	p_old_madw = (osm_madw_t *) transaction_context;

	__osm_sm_mad_ctrl_update_wire_stats(p_ctrl);

	/*
	   Copy the MAD Wrapper context from the requesting MAD
	   to the new MAD.  This mechanism allows the recipient
	   controller to recover its own context regarding this
	   MAD transaction.  Once we've copied the context, we
	   can return the original MAD to the pool.
	 */
	osm_madw_copy_context(p_madw, p_old_madw);
	osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw);

	/*
	   Note that attr_id (like the rest of the MAD) is in
	   network byte order.
	 */
	switch (p_smp->attr_id) {
	case IB_MAD_ATTR_NODE_DESC:
		msg_id = OSM_MSG_MAD_NODE_DESC;
		break;
	case IB_MAD_ATTR_NODE_INFO:
		msg_id = OSM_MSG_MAD_NODE_INFO;
		break;
	case IB_MAD_ATTR_SWITCH_INFO:
		msg_id = OSM_MSG_MAD_SWITCH_INFO;
		break;
	case IB_MAD_ATTR_PORT_INFO:
		msg_id = OSM_MSG_MAD_PORT_INFO;
		break;
	case IB_MAD_ATTR_LIN_FWD_TBL:
		msg_id = OSM_MSG_MAD_LFT;
		break;
	case IB_MAD_ATTR_MCAST_FWD_TBL:
		msg_id = OSM_MSG_MAD_MFT;
		break;
	case IB_MAD_ATTR_SM_INFO:
		msg_id = OSM_MSG_MAD_SM_INFO;
		break;
	case IB_MAD_ATTR_SLVL_TABLE:
		msg_id = OSM_MSG_MAD_SLVL;
		break;
	case IB_MAD_ATTR_VL_ARBITRATION:
		msg_id = OSM_MSG_MAD_VL_ARB;
		break;
	case IB_MAD_ATTR_P_KEY_TABLE:
		msg_id = OSM_MSG_MAD_PKEY;
		break;

	case IB_MAD_ATTR_GUID_INFO:
	case IB_MAD_ATTR_CLASS_PORT_INFO:
	case IB_MAD_ATTR_NOTICE:
	case IB_MAD_ATTR_INFORM_INFO:
	default:
		cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown);
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: "
			"Unsupported attribute = 0x%X\n",
			cl_ntoh16(p_smp->attr_id));
		osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR);
		goto Exit;
	}

	if (msg_id == CL_DISP_MSGID_NONE)
		goto Exit;

	/*
	   Post this MAD to the dispatcher for asynchronous
	   processing by the appropriate controller.
	 */

	OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n",
		osm_get_disp_msg_str(msg_id));

	status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw,
			      __osm_sm_mad_ctrl_disp_done_callback, p_ctrl);

	if (status != CL_SUCCESS) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: "
			"Dispatcher post message failed (%s) for attribute = 0x%X\n",
			CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id));
		goto Exit;
	}

Exit:
	OSM_LOG_EXIT(p_ctrl->p_log);
}
/* Send a MAD out on the GSI interface */
static ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc)
	 */
	if (time(NULL) > p_bind->last_lids_update_sec + 30) {
		status = update_umad_port(p_bind->p_vendor);
		if (status != IB_SUCCESS) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5509: "
				"Failed to obtain the SM lid\n");
			goto Exit;
		}
		p_bind->last_lids_update_sec = time(NULL);
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5510: "
			"Unable to acquire MAD\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */);

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
#ifdef DUAL_SIDED_RMPP
	if (p_sa_mad->method == IB_MAD_METHOD_GETMULTI)
		p_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
#endif
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	p_madw->mad_addr.dest_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.sm_lid);
	p_madw->mad_addr.addr_type.smi.source_lid =
	    cl_hton16(p_bind->p_vendor->umad_port.base_lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it around until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.ni_context.node_guid
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.ni_context.node_guid =
	    (ib_net64_t) (long)p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		OSM_LOG(p_log, OSM_LOG_DEBUG, "Waiting for async event\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
Beispiel #10
0
/* Send a MAD out on the GSI interface */
ib_api_status_t
__osmv_send_sa_req(IN osmv_sa_bind_info_t * p_bind,
		   IN const osmv_sa_mad_data_t * const p_sa_mad_data,
		   IN const osmv_query_req_t * const p_query_req)
{
	ib_api_status_t status;
	ib_mad_t *p_mad_hdr;
	ib_sa_mad_t *p_sa_mad;
	osm_madw_t *p_madw;
	osm_log_t *p_log = p_bind->p_log;
	static atomic32_t trans_id;
	boolean_t sync;
	osmv_query_req_t *p_query_req_copy;

	OSM_LOG_ENTER(p_log);

	/*
	   since the sm_lid might change we obtain it every send
	   (actually it is cached in the bind object and refreshed
	   every 30sec by this proc )
	 */
	status =
	    __osmv_get_lid_and_sm_lid_by_port_guid(p_bind->p_vendor,
						   p_bind->port_guid,
						   &p_bind->
						   last_lids_update_sec,
						   &p_bind->lid,
						   &p_bind->sm_lid);
	if (status != IB_SUCCESS) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0509: "
			"Fail to obtain the sm lid.\n");
		goto Exit;
	}

	/* Get a MAD wrapper for the send */
	p_madw = osm_mad_pool_get(p_bind->p_mad_pool,
				  p_bind->h_bind, MAD_BLOCK_SIZE, NULL);

	if (p_madw == NULL) {
		osm_log(p_log, OSM_LOG_ERROR,
			"__osmv_send_sa_req: ERR 0510: "
			"Unable to acquire MAD.\n");
		status = IB_INSUFFICIENT_RESOURCES;
		goto Exit;
	}

	/* Initialize the Sent MAD: */

	/* Initialize the MAD buffer for the send operation. */
	p_mad_hdr = osm_madw_get_mad_ptr(p_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/* Get a new transaction Id */
	cl_atomic_inc(&trans_id);

	/* Cleanup the MAD from any residue */
	memset(p_sa_mad, 0, MAD_BLOCK_SIZE);

	/* Initialize the standard MAD header. */
	ib_mad_init_new(p_mad_hdr,	/* mad pointer */
			IB_MCLASS_SUBN_ADM,	/* class */
			(uint8_t) 2,	/* version */
			p_sa_mad_data->method,	/* method */
			cl_hton64((uint64_t) trans_id),	/* tid */
			p_sa_mad_data->attr_id,	/* attr id */
			p_sa_mad_data->attr_mod	/* attr mod */
	    );

	/* Set the query information. */
	p_sa_mad->sm_key = p_query_req->sm_key;
	p_sa_mad->attr_offset = 0;
	p_sa_mad->comp_mask = p_sa_mad_data->comp_mask;
	if (p_sa_mad->comp_mask) {
		memcpy(p_sa_mad->data, p_sa_mad_data->p_attr,
		       ib_get_attr_size(p_sa_mad_data->attr_offset));
	}

	/*
	   Provide the address to send to
	 */
	/* Patch to handle IBAL - host order , where it should take destination lid in network order */
#ifdef OSM_VENDOR_INTF_AL
	p_madw->mad_addr.dest_lid = p_bind->sm_lid;
#else
	p_madw->mad_addr.dest_lid = cl_hton16(p_bind->sm_lid);
#endif
	p_madw->mad_addr.addr_type.smi.source_lid = cl_hton16(p_bind->lid);
	p_madw->mad_addr.addr_type.gsi.remote_qp = CL_HTON32(1);
	p_madw->mad_addr.addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
	p_madw->mad_addr.addr_type.gsi.pkey_ix = 0;
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	/*
	   Provide MAD context such that the call back will know what to do.
	   We have to keep the entire request structure so we know the CB.
	   Since we can not rely on the client to keep it arroud until
	   the response - we duplicate it and will later dispose it (in CB).
	   To store on the MADW we cast it into what opensm has:
	   p_madw->context.arb_context.context1
	 */
	p_query_req_copy = malloc(sizeof(*p_query_req_copy));
	*p_query_req_copy = *p_query_req;
	p_madw->context.arb_context.context1 = p_query_req_copy;

	/* we can support async as well as sync calls */
	sync = ((p_query_req->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC);

	/* send the mad asynchronously */
	status = osm_vendor_send(osm_madw_get_bind_handle(p_madw),
				 p_madw, p_madw->resp_expected);

	/* if synchronous - wait on the event */
	if (sync) {
		osm_log(p_log, OSM_LOG_DEBUG,
			"__osmv_send_sa_req: " "Waiting for async event.\n");
		cl_event_wait_on(&p_bind->sync_event, EVENT_NO_TIMEOUT, FALSE);
		cl_event_reset(&p_bind->sync_event);
		status = p_madw->status;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return status;
}
Beispiel #11
0
int osm_send_trap144(osm_sm_t * sm, ib_net16_t local)
{
	osm_madw_t *madw;
	ib_smp_t *smp;
	ib_mad_notice_attr_t *ntc;
	osm_port_t *port, *smport;
	ib_port_info_t *pi;

	port = osm_get_port_by_guid(sm->p_subn, sm->p_subn->sm_port_guid);
	if (!port) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1104: cannot find SM port by guid 0x%" PRIx64 "\n",
			cl_ntoh64(sm->p_subn->sm_port_guid));
		return -1;
	}

	pi = &port->p_physp->port_info;

	/* don't bother with sending trap when SMA supports this */
	if (!local &&
	    pi->capability_mask&(IB_PORT_CAP_HAS_TRAP|IB_PORT_CAP_HAS_CAP_NTC))
		return 0;

	smport = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid);
	if (!smport) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1106: cannot find master SM port by guid 0x%" PRIx64 "\n",
			cl_ntoh64(sm->master_sm_guid));
		return -1;
	}

	madw = osm_mad_pool_get(sm->p_mad_pool,
				osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl),
				MAD_BLOCK_SIZE, NULL);
	if (madw == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1105: Unable to acquire MAD\n");
		return -1;
	}

	madw->mad_addr.dest_lid = smport->p_physp->port_info.base_lid;
	madw->mad_addr.addr_type.smi.source_lid = pi->base_lid;
	madw->resp_expected = TRUE;
	madw->fail_msg = CL_DISP_MSGID_NONE;

	smp = osm_madw_get_smp_ptr(madw);
	memset(smp, 0, sizeof(*smp));

	smp->base_ver = 1;
	smp->mgmt_class = IB_MCLASS_SUBN_LID;
	smp->class_ver = 1;
	smp->method = IB_MAD_METHOD_TRAP;
	smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
							   & (uint64_t)(0xFFFFFFFF));
	if (smp->trans_id == 0)
		smp->trans_id = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
								   & (uint64_t)(0xFFFFFFFF));

	smp->attr_id = IB_MAD_ATTR_NOTICE;

	ntc = (ib_mad_notice_attr_t *) smp->data;

	ntc->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
	ib_notice_set_prod_type_ho(ntc, osm_node_get_type(port->p_node));
	ntc->g_or_v.generic.trap_num = cl_hton16(SM_LOCAL_CHANGES_TRAP); /* 144 */
	ntc->issuer_lid = pi->base_lid;
	ntc->data_details.ntc_144.lid = pi->base_lid;
	ntc->data_details.ntc_144.local_changes = local ?
	    TRAP_144_MASK_OTHER_LOCAL_CHANGES : 0;
	ntc->data_details.ntc_144.new_cap_mask = pi->capability_mask;
	ntc->data_details.ntc_144.change_flgs = local;

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Sending Trap 144, TID 0x%" PRIx64 " to SM lid %u\n",
		cl_ntoh64(smp->trans_id), cl_ntoh16(madw->mad_addr.dest_lid));

	osm_vl15_post(sm->p_vl15, madw);

	return 0;
}
Beispiel #12
0
/**********************************************************************
  The plock must be held before calling this function.
**********************************************************************/
osm_madw_t *osm_prepare_req_set(IN osm_sm_t * sm, IN const osm_dr_path_t * p_path,
				IN const uint8_t * p_payload,
				IN size_t payload_size,
				IN ib_net16_t attr_id, IN ib_net32_t attr_mod,
				IN boolean_t find_mkey, IN ib_net64_t m_key,
				IN cl_disp_msgid_t err_msg,
				IN const osm_madw_context_t * p_context)
{
	osm_madw_t *p_madw = NULL;
	ib_net64_t m_key_calc;
	ib_net64_t tid;

	CL_ASSERT(sm);

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_path);
	CL_ASSERT(attr_id);
	CL_ASSERT(p_payload);

	/* do nothing if we are exiting ... */
	if (osm_exit_flag)
		goto Exit;

	/* p_context may be NULL. */

	p_madw = osm_mad_pool_get(sm->p_mad_pool, sm->mad_ctrl.h_bind,
				  MAD_BLOCK_SIZE, NULL);
	if (p_madw == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 1102: Unable to acquire MAD\n");
		goto Exit;
	}

	tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
						 & (uint64_t)(0xFFFFFFFF));
	if (tid == 0)
		tid = cl_hton64((uint64_t) cl_atomic_inc(&sm->sm_trans_id)
							 & (uint64_t)(0xFFFFFFFF));

	if (sm->p_subn->opt.m_key_lookup == TRUE) {
		if (find_mkey == TRUE)
			m_key_calc = req_determine_mkey(sm, p_path);
		else
			m_key_calc = m_key;
	} else
		m_key_calc = sm->p_subn->opt.m_key;

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Setting %s (0x%X), modifier 0x%X, TID 0x%" PRIx64
		", MKey 0x%016" PRIx64 "\n",
		ib_get_sm_attr_str(attr_id), cl_ntoh16(attr_id),
		cl_ntoh32(attr_mod), cl_ntoh64(tid), cl_ntoh64(m_key_calc));

	ib_smp_init_new(osm_madw_get_smp_ptr(p_madw), IB_MAD_METHOD_SET,
			tid, attr_id, attr_mod, p_path->hop_count,
			m_key_calc, p_path->path,
			IB_LID_PERMISSIVE, IB_LID_PERMISSIVE);

	p_madw->mad_addr.dest_lid = IB_LID_PERMISSIVE;
	p_madw->mad_addr.addr_type.smi.source_lid = IB_LID_PERMISSIVE;
	p_madw->resp_expected = TRUE;
	p_madw->fail_msg = err_msg;

	/*
	   Fill in the mad wrapper context for the recipient.
	   In this case, the only thing the recipient needs is the
	   guid value.
	 */

	if (p_context)
		p_madw->context = *p_context;

	memcpy(osm_madw_get_smp_ptr(p_madw)->data, p_payload, payload_size);

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return p_madw;
}