Exemple #1
0
void osm_lft_rcv_process(IN void *context, IN void *data)
{
	osm_sm_t *sm = context;
	osm_madw_t *p_madw = data;
	ib_smp_t *p_smp;
	uint32_t block_num;
	osm_switch_t *p_sw;
	osm_lft_context_t *p_lft_context;
	uint8_t *p_block;
	ib_net64_t node_guid;
	ib_api_status_t status;

	CL_ASSERT(sm);

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_madw);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_block = ib_smp_get_payload_ptr(p_smp);
	block_num = cl_ntoh32(p_smp->attr_mod);

	/*
	   Acquire the switch object for this switch.
	 */
	p_lft_context = osm_madw_get_lft_context_ptr(p_madw);
	node_guid = p_lft_context->node_guid;

	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
	p_sw = osm_get_switch_by_guid(sm->p_subn, node_guid);

	if (!p_sw) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0401: "
			"LFT received for nonexistent node "
			"0x%" PRIx64 "\n", cl_ntoh64(node_guid));
	} else {
		status = osm_switch_set_lft_block(p_sw, p_block, block_num);
		if (status != IB_SUCCESS) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0402: "
				"Setting forwarding table block failed (%s)"
				", Switch 0x%" PRIx64 " %s\n",
				ib_get_err_str(status), cl_ntoh64(node_guid),
				p_sw->p_node->print_desc);
		}
	}

	CL_PLOCK_RELEASE(sm->p_lock);
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #2
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;
}
Exemple #3
0
static void sm_state_mgr_send_master_sm_info_req(osm_sm_t * sm)
{
	osm_madw_context_t context;
	const osm_port_t *p_port;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

	memset(&context, 0, sizeof(context));
	if (sm->p_subn->sm_state == IB_SMINFO_STATE_STANDBY) {
		/*
		 * We are in STANDBY state - this means we need to poll the
		 * master SM (according to master_guid).
		 * Send a query of SubnGet(SMInfo) to the subn
		 * master_sm_base_lid object.
		 */
		p_port = osm_get_port_by_guid(sm->p_subn, sm->master_sm_guid);
	} else {
		/*
		 * We are not in STANDBY - this means we are in MASTER state -
		 * so we need to poll the SM that is saved in p_polling_sm
		 * under sm.
		 * Send a query of SubnGet(SMInfo) to that SM.
		 */
		p_port = sm->p_polling_sm->p_port;
	}
	if (p_port == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3203: "
			"No port object for GUID 0x%016" PRIx64 "\n",
			cl_ntoh64(sm->master_sm_guid));
		goto Exit;
	}

	context.smi_context.port_guid = p_port->guid;
	context.smi_context.set_method = FALSE;

	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
			     IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE,
			     &context);

	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3204: "
			"Failure requesting SMInfo (%s)\n",
			ib_get_err_str(status));

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #4
0
static void query_sm_info(cl_map_item_t * item, void *cxt)
{
	osm_madw_context_t context;
	osm_remote_sm_t *r_sm = cl_item_obj(item, r_sm, map_item);
	osm_sm_t *sm = cxt;
	ib_api_status_t ret;

	context.smi_context.port_guid = r_sm->p_port->guid;
	context.smi_context.set_method = FALSE;
	context.smi_context.light_sweep = TRUE;

	ret = osm_req_get(sm, osm_physp_get_dr_path_ptr(r_sm->p_port->p_physp),
			  IB_MAD_ATTR_SM_INFO, 0, CL_DISP_MSGID_NONE, &context);
	if (ret != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3314: "
			"Failure requesting SMInfo (%s)\n",
			ib_get_err_str(ret));
}
Exemple #5
0
ib_mad_t *osm_vendor_get(IN osm_bind_handle_t h_bind,
			 IN const uint32_t mad_size,
			 IN osm_vend_wrap_t * const p_vw)
{
	ib_mad_t *p_mad;
	osm_al_bind_info_t *p_bind = (osm_al_bind_info_t *) h_bind;
	osm_vendor_t *p_vend = p_bind->p_vend;
	ib_api_status_t status;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_vw);

	p_vw->size = mad_size;
	p_vw->h_bind = h_bind;

	/*
	   Retrieve a MAD element from the pool and give the user direct
	   access to its buffer.
	 */
	status = ib_get_mad(p_bind->pool_key, mad_size, &p_vw->p_elem);
	if (status != IB_SUCCESS) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_get: ERR 3B25: "
			"Unable to acquire MAD (%s).\n",
			ib_get_err_str(status));

		p_mad = NULL;
		goto Exit;
	}

	CL_ASSERT(p_vw->p_elem);
	p_mad = ib_get_mad_buf(p_vw->p_elem);

	if (osm_log_get_level(p_vend->p_log) >= OSM_LOG_DEBUG) {
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
			"osm_vendor_get: "
			"Acquired MAD %p, size = %u.\n", p_mad, mad_size);
	}

Exit:
	OSM_LOG_EXIT(p_vend->p_log);
	return (p_mad);
}
Exemple #6
0
ib_api_status_t osm_sa_bind(IN osm_sa_t * p_sa, IN ib_net64_t port_guid)
{
	ib_api_status_t status;

	OSM_LOG_ENTER(p_sa->p_log);

	status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid);

	if (status != IB_SUCCESS) {
		OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: "
			"SA MAD Controller bind failed (%s)\n",
			ib_get_err_str(status));
		goto Exit;
	}

Exit:
	OSM_LOG_EXIT(p_sa->p_log);
	return status;
}
Exemple #7
0
/**********************************************************************
 Initiate a remote port info request for the given physical port
 **********************************************************************/
static void state_mgr_get_remote_port_info(IN osm_sm_t * sm,
					   IN osm_physp_t * p_physp)
{
	osm_dr_path_t *p_dr_path;
	osm_dr_path_t rem_node_dr_path;
	osm_madw_context_t mad_context;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

	/* generate a dr path leaving on the physp to the remote node */
	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
	memcpy(&rem_node_dr_path, p_dr_path, sizeof(osm_dr_path_t));
	if (osm_dr_path_extend(&rem_node_dr_path, osm_physp_get_port_num(p_physp))) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332D: "
			"DR path with hop count %d couldn't be extended "
			"so skipping PortInfo query\n",
			p_dr_path->hop_count);
		goto Exit;
	}

	memset(&mad_context, 0, sizeof(mad_context));

	mad_context.pi_context.node_guid =
	    osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp));
	mad_context.pi_context.port_guid = p_physp->port_guid;
	mad_context.pi_context.set_method = FALSE;
	mad_context.pi_context.light_sweep = TRUE;
	mad_context.pi_context.active_transition = FALSE;

	/* note that with some negative logic - if the query failed it means
	 * that there is no point in going to heavy sweep */
	status = osm_req_get(sm, &rem_node_dr_path, IB_MAD_ATTR_PORT_INFO, 0,
			     CL_DISP_MSGID_NONE, &mad_context);
	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 332E: "
			"Request for PortInfo failed (%s)\n",
			ib_get_err_str(status));

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #8
0
static void state_mgr_update_node_desc(IN cl_map_item_t * obj, IN void *context)
{
	osm_madw_context_t mad_context;
	osm_node_t *p_node = (osm_node_t *) obj;
	osm_sm_t *sm = context;
	osm_physp_t *p_physp = NULL;
	unsigned i, num_ports;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_node);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Updating NodeDesc for 0x%016" PRIx64 "\n",
		cl_ntoh64(osm_node_get_node_guid(p_node)));

	/* get a physp to request from. */
	num_ports = osm_node_get_num_physp(p_node);
	for (i = 0; i < num_ports; i++)
		if ((p_physp = osm_node_get_physp_ptr(p_node, i)))
			break;

	if (!p_physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: "
			"Failed to find any valid physical port object.\n");
		goto exit;
	}

	mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node);

	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
			     IB_MAD_ATTR_NODE_DESC, 0, CL_DISP_MSGID_NONE,
			     &mad_context);
	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 331B: Failure initiating NodeDescription request "
			"(%s)\n", ib_get_err_str(status));

exit:
	OSM_LOG_EXIT(sm->p_log);
}
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void si_rcv_get_fwd_tbl(IN osm_sm_t * sm, IN osm_switch_t * p_sw)
{
	osm_madw_context_t context;
	osm_dr_path_t *p_dr_path;
	osm_physp_t *p_physp;
	osm_node_t *p_node;
	uint32_t block_id_ho;
	uint32_t max_block_id_ho;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_sw);

	p_node = p_sw->p_node;

	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);

	context.lft_context.node_guid = osm_node_get_node_guid(p_node);
	context.lft_context.set_method = FALSE;

	max_block_id_ho = osm_switch_get_max_block_id_in_use(p_sw);

	p_physp = osm_node_get_physp_ptr(p_node, 0);
	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);

	for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Retrieving FT block %u\n", block_id_ho);

		status = osm_req_get(sm, p_dr_path, IB_MAD_ATTR_LIN_FWD_TBL,
				     cl_hton32(block_id_ho),
				     CL_DISP_MSGID_NONE, &context);
		if (status != IB_SUCCESS)
			/* continue the loop despite the error */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3603: "
				"Failure initiating PortInfo request (%s)\n",
				ib_get_err_str(status));
	}

	OSM_LOG_EXIT(sm->p_log);
}
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t * p_physp)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_madw_context_t context;

	OSM_LOG_ENTER(sm->p_log);

	context.nd_context.node_guid =
	    osm_node_get_node_guid(osm_physp_get_node_ptr(p_physp));

	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
			     IB_MAD_ATTR_NODE_DESC, 0, TRUE, 0,
			     CL_DISP_MSGID_NONE, &context);
	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D03: "
			"Failure initiating NodeDescription request (%s)\n",
			ib_get_err_str(status));

	OSM_LOG_EXIT(sm->p_log);
}
static void requery_dup_node_info(IN osm_sm_t * sm, osm_physp_t * p_physp,
				  unsigned count)
{
	osm_madw_context_t context;
	osm_dr_path_t path;
	cl_status_t status;

	if (!p_physp->p_remote_physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0D: "
			"DR path couldn't be extended due to NULL remote physp\n");
		return;
	}

	path = *osm_physp_get_dr_path_ptr(p_physp->p_remote_physp);
	if (osm_dr_path_extend(&path, p_physp->p_remote_physp->port_num)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D08: "
			"DR path with hop count %d couldn't be extended\n",
			path.hop_count);
		return;
	}

	context.ni_context.node_guid =
	    p_physp->p_remote_physp->p_node->node_info.port_guid;
	context.ni_context.port_num = p_physp->p_remote_physp->port_num;
	context.ni_context.dup_node_guid = p_physp->p_node->node_info.node_guid;
	context.ni_context.dup_port_num = p_physp->port_num;
	context.ni_context.dup_count = count;

	status = osm_req_get(sm, &path, IB_MAD_ATTR_NODE_INFO, 0,
			     TRUE, 0, CL_DISP_MSGID_NONE, &context);

	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D02: "
			"Failure initiating NodeInfo request (%s)\n",
			ib_get_err_str(status));
}
/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb
 * NAME
 * __osm_sm_mad_ctrl_send_err_cb
 *
 * DESCRIPTION
 * This is the callback from the transport layer for send errors
 * on MADs that were expecting a response.
 *
 * SYNOPSIS
 */
static void
__osm_sm_mad_ctrl_send_err_cb(IN void *bind_context, IN osm_madw_t * p_madw)
{
	osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context;
	ib_api_status_t status;
	ib_smp_t *p_smp;

	OSM_LOG_ENTER(p_ctrl->p_log);

	CL_ASSERT(p_madw);

	OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: "
		"MAD completed in error (%s)\n",
		ib_get_err_str(p_madw->status));

	/*
	   If this was a SubnSet MAD, then this error might indicate a problem
	   in configuring the subnet. In this case - need to mark that there was
	   such a problem. The subnet will not be up, and the next sweep should
	   be a heavy sweep as well.
	 */
	p_smp = osm_madw_get_smp_ptr(p_madw);
	if (p_smp->method == IB_MAD_METHOD_SET &&
	    (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO ||
	     p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL ||
	     p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO ||
	     p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL)) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: "
			"Set method failed\n");
		p_ctrl->p_subn->subnet_initialization_error = TRUE;
	}

	/*
	   Since we did not get any response we suspect the DR path
	   used for the target port.
	   Find it and replace it with an alternate path.
	   This is true only if the destination lid is not 0xFFFF, since
	   then we are aiming for a specific path and not specific destination
	   lid.
	 */
	/* For now - do not add the alternate dr path to the release */
#if 0
	if (p_madw->mad_addr.dest_lid != 0xFFFF) {
		osm_physp_t *p_physp =
		    osm_get_physp_by_mad_addr(p_ctrl->p_log,
					      p_ctrl->p_subn,
					      &(p_madw->mad_addr));
		if (!p_physp) {
			OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: "
				"Failed to find the corresponding phys port\n");
		} else {
			osm_physp_replace_dr_path_with_alternate_dr_path
			    (p_ctrl->p_log, p_ctrl->p_subn, p_physp,
			     p_madw->h_bind);
		}
	}
#endif

	/*
	   An error occurred.  No response was received to a request MAD.
	   Retire the original request MAD.
	 */

	osm_dump_dr_smp(p_ctrl->p_log, osm_madw_get_smp_ptr(p_madw),
			OSM_LOG_ERROR);

	__osm_sm_mad_ctrl_update_wire_stats(p_ctrl);

	if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) {
		OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG,
			"Posting Dispatcher message %s\n",
			osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw)));

		status = cl_disp_post(p_ctrl->h_disp,
				      osm_madw_get_err_msg(p_madw),
				      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 3115: "
				"Dispatcher post message failed (%s)\n",
				CL_STATUS_MSG(status));
	} else
		/*
		   No error message was provided, just retire the MAD.
		 */
		__osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw);

	OSM_LOG_EXIT(p_ctrl->p_log);
}
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void si_rcv_get_mcast_fwd_tbl(IN osm_sm_t * sm, IN osm_switch_t * p_sw)
{
	osm_madw_context_t context;
	osm_dr_path_t *p_dr_path;
	osm_physp_t *p_physp;
	osm_node_t *p_node;
	osm_mcast_tbl_t *p_tbl;
	uint32_t block_id_ho;
	uint32_t max_block_id_ho;
	uint32_t position;
	uint32_t max_position;
	uint32_t attr_mod_ho;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_sw);

	p_node = p_sw->p_node;

	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);

	if (osm_switch_get_mcast_fwd_tbl_size(p_sw) == 0) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Multicast not supported by switch 0x%016" PRIx64 "\n",
			cl_ntoh64(osm_node_get_node_guid(p_node)));
		goto Exit;
	}

	context.mft_context.node_guid = osm_node_get_node_guid(p_node);
	context.mft_context.set_method = FALSE;

	p_tbl = osm_switch_get_mcast_tbl_ptr(p_sw);
	max_block_id_ho = osm_mcast_tbl_get_max_block(p_tbl);

	if (max_block_id_ho > IB_MCAST_MAX_BLOCK_ID) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3609: "
			"Out-of-range mcast block size = %u on switch 0x%016"
			PRIx64 "\n", max_block_id_ho,
			cl_ntoh64(osm_node_get_node_guid(p_node)));
		goto Exit;
	}

	max_position = osm_mcast_tbl_get_max_position(p_tbl);

	CL_ASSERT(max_position <= IB_MCAST_POSITION_MAX);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Max MFT block = %u, Max position = %u\n", max_block_id_ho,
		max_position);

	p_physp = osm_node_get_physp_ptr(p_node, 0);
	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);

	for (block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Retrieving MFT block %u\n", block_id_ho);

		for (position = 0; position <= max_position; position++) {
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Retrieving MFT position %u\n", position);

			attr_mod_ho =
			    block_id_ho | position << IB_MCAST_POSITION_SHIFT;
			status =
			    osm_req_get(sm, p_dr_path,
					IB_MAD_ATTR_MCAST_FWD_TBL,
					cl_hton32(attr_mod_ho),
					CL_DISP_MSGID_NONE, &context);
			if (status != IB_SUCCESS)
				/* continue the loop despite the error */
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3607: "
					"Failure initiating PortInfo request (%s)\n",
					ib_get_err_str(status));
		}
	}

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #14
0
ib_api_status_t
osmv_rmpp_send_madw(IN osm_bind_handle_t h_bind,
		    IN osm_madw_t * const p_madw,
		    IN osmv_txn_ctx_t * p_txn, IN boolean_t is_rmpp_ds)
{
	ib_api_status_t ret = IB_SUCCESS;
	uint32_t i, total_segs;

	osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
	CL_ASSERT(total_segs >= 1);

	/* In the double-sided transfer, wait for ACK 0 */

	for (;;) {

		if (p_send_ctx->window_first > total_segs) {

			/* Every segment is acknowledged */
			break;
		}

		/* Send the next burst. */
		for (i = p_send_ctx->window_first; i <= p_send_ctx->window_last;
		     i++) {

			/* Send a segment and setup a timeout timer */
			ret = __osmv_rmpp_send_segment(h_bind, p_txn, i);
			if (IB_SUCCESS != ret) {
				goto send_done;
			}
		}

		/* Set the Response Timeout for the ACK on the last DATA segment */
		ret = osmv_txn_set_timeout_ev(h_bind, osmv_txn_get_key(p_txn),
					      p_bo->p_vendor->resp_timeout);
		if (IB_SUCCESS != ret) {
			goto send_done;
		}

		/* Going to sleep. Let the others access the transaction DB */
		osmv_txn_unlock(p_bo);

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"RMPP Sender thread (madw=%p) going to sleep ...\n",
			p_madw);

		/* Await the next event to happen */
		cl_event_wait_on(&p_send_ctx->event,
				 EVENT_NO_TIMEOUT, TRUE /* interruptible */ );

		/* Got a signal from the MAD dispatcher/timeout handler */
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"RMPP Sender thread (madw=%p) waking up on a signal ...\n",
			p_madw);

		/* Let's see what changed... Make this atomic - re-acquire the lock. */
		osmv_txn_lock(p_bo);

		if (TRUE == p_bo->is_closing) {
			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
				"osmv_rmpp_send_madw: ERR 6601: "
				"The bind handle %p is being closed. "
				"Stopping the RMPP Send of MADW %p\n",
				h_bind, p_madw);

			ret = IB_TIMEOUT;
			return IB_INTERRUPTED;
		}

		/* STOP? ABORT? TIMEOUT? */
		if (IB_SUCCESS != p_send_ctx->status) {
			osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
				"osmv_rmpp_send_madw: ERR 6602: "
				"An error (%s) happened during the RMPP send of %p. Bailing out.\n",
				ib_get_err_str(p_send_ctx->status), p_madw);
			ret = p_send_ctx->status;
			goto send_done;
		}
	}

	if (TRUE == is_rmpp_ds) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Double-sided RMPP - switching to be the receiver.\n");

		ret = osmv_txn_init_rmpp_receiver(h_bind, p_txn, FALSE
						  /*Send was initiated by me */
						  );

		if (IB_SUCCESS == ret) {
			/* Send ACK on the 0 segment */
			ret = __osmv_rmpp_send_segment(h_bind, p_txn, 0);
		}
	}

send_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return ret;
}
osm_bind_handle_t
osmv_bind_sa(IN osm_vendor_t * const p_vend,
	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
{
	osm_bind_info_t bind_info;
	osm_log_t *p_log = p_vend->p_log;
	osmv_sa_bind_info_t *p_sa_bind_info;
	cl_status_t cl_status;

	OSM_LOG_ENTER(p_log);

	OSM_LOG(p_log, OSM_LOG_DEBUG,
		"Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid));

	bind_info.port_guid = port_guid;
	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
	bind_info.class_version = 2;
	bind_info.is_responder = FALSE;
	bind_info.is_trap_processor = FALSE;
	bind_info.is_report_processor = FALSE;
	bind_info.send_q_size = OSM_SM_DEFAULT_QP1_RCV_SIZE;
	bind_info.recv_q_size = OSM_SM_DEFAULT_QP1_SEND_SIZE;

	/* allocate the new sa bind info */
	p_sa_bind_info =
	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
	if (!p_sa_bind_info) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5505: "
			"Failed to allocate new bind structure\n");
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
		goto Exit;
	}

	/* store some important context */
	p_sa_bind_info->p_log = p_log;
	p_sa_bind_info->p_mad_pool = p_mad_pool;
	p_sa_bind_info->p_vendor = p_vend;

	/* Bind to the lower level */
	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */

	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
		free(p_sa_bind_info);
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5506: "
			"Failed to bind to vendor GSI\n");
		goto Exit;
	}

	/* update time umad_port is initilized now */
	p_sa_bind_info->last_lids_update_sec = time(NULL);

	/* initialize the sync_event */
	cl_event_construct(&p_sa_bind_info->sync_event);
	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
	if (cl_status != CL_SUCCESS) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 5508: "
			"cl_init_event failed: %s\n", ib_get_err_str(cl_status));
		free(p_sa_bind_info);
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return (p_sa_bind_info);
}
Exemple #16
0
/**********************************************************************
 * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
 * remote_sm indicated.
 **********************************************************************/
static void state_mgr_send_handover(IN osm_sm_t * sm, IN osm_remote_sm_t * p_sm)
{
	uint8_t payload[IB_SMP_DATA_SIZE];
	ib_sm_info_t *p_smi = (ib_sm_info_t *) payload;
	osm_madw_context_t context;
	const osm_port_t *p_port;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

	/*
	 * Send a query of SubnSet(SMInfo) HANDOVER to the remote sm given.
	 */

	memset(&context, 0, sizeof(context));
	p_port = p_sm->p_port;
	if (p_port == NULL) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3316: "
			"No port object on given remote_sm object\n");
		goto Exit;
	}

	/* update the master_guid in the sm_state_mgr object according to */
	/* the guid of the port where the new Master SM should reside. */
	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
		"Handing over mastership. Updating sm_state_mgr master_guid: %016"
		PRIx64 " (node %s)\n", cl_ntoh64(p_port->guid),
		p_port->p_node ? p_port->p_node->print_desc : "UNKNOWN");
	sm->master_sm_guid = p_port->guid;

	context.smi_context.port_guid = p_port->guid;
	context.smi_context.set_method = TRUE;

	p_smi->guid = sm->p_subn->sm_port_guid;
	p_smi->act_count = cl_hton32(sm->p_subn->p_osm->stats.qp0_mads_sent);
	p_smi->pri_state = (uint8_t) (sm->p_subn->sm_state |
				      sm->p_subn->opt.sm_priority << 4);
	/*
	 * Return 0 for the SM key unless we authenticate the requester
	 * as the master SM.
	 */
	if (ib_sminfo_get_state(&p_sm->smi) == IB_SMINFO_STATE_MASTER) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Responding to master SM with real sm_key\n");
		p_smi->sm_key = sm->p_subn->opt.sm_key;
	} else {
		/* The requester is not authenticated as master - set sm_key to zero */
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Responding to SM not master with zero sm_key\n");
		p_smi->sm_key = 0;
	}

	status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_port->p_physp),
			     payload, sizeof(payload), IB_MAD_ATTR_SM_INFO,
			     IB_SMINFO_ATTR_MOD_HANDOVER, CL_DISP_MSGID_NONE,
			     &context);

	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3317: "
			"Failure requesting SMInfo (%s)\n",
			ib_get_err_str(status));

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #17
0
/**********************************************************************
 * Send Trap 64 on all new ports.
 **********************************************************************/
static void state_mgr_report_new_ports(IN osm_sm_t * sm)
{
	ib_gid_t port_gid;
	ib_mad_notice_attr_t notice;
	ib_api_status_t status;
	ib_net64_t port_guid;
	cl_map_item_t *p_next;
	osm_port_t *p_port;
	uint16_t min_lid_ho;
	uint16_t max_lid_ho;

	OSM_LOG_ENTER(sm->p_log);

	CL_PLOCK_ACQUIRE(sm->p_lock);
	p_next = cl_qmap_head(&sm->p_subn->port_guid_tbl);
	while (p_next != cl_qmap_end(&sm->p_subn->port_guid_tbl)) {
		p_port = (osm_port_t *) p_next;
		p_next = cl_qmap_next(p_next);

		if (!p_port->is_new)
			continue;

		port_guid = osm_port_get_guid(p_port);
		/* issue a notice - trap 64 */

		/* details of the notice */
		notice.generic_type = 0x83;	/* is generic subn mgt type */
		ib_notice_set_prod_type_ho(&notice, 4);	/* A Class Manager generator */
		/* endport becomes reachable */
		notice.g_or_v.generic.trap_num = CL_HTON16(64);
		/* The sm_base_lid is saved in network order already. */
		notice.issuer_lid = sm->p_subn->sm_base_lid;
		/* following C14-72.1.1 and table 119 p739 */
		/* we need to provide the GID */
		port_gid.unicast.prefix = sm->p_subn->opt.subnet_prefix;
		port_gid.unicast.interface_id = port_guid;
		memcpy(&(notice.data_details.ntc_64_67.gid), &(port_gid),
		       sizeof(ib_gid_t));

		/* According to page 653 - the issuer gid in this case of trap
		 * is the SM gid, since the SM is the initiator of this trap. */
		notice.issuer_gid.unicast.prefix =
		    sm->p_subn->opt.subnet_prefix;
		notice.issuer_gid.unicast.interface_id =
		    sm->p_subn->sm_port_guid;

		status = osm_report_notice(sm->p_log, sm->p_subn, &notice);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3318: "
				"Error sending trap reports on GUID:0x%016"
				PRIx64 " (%s)\n", port_gid.unicast.interface_id,
				ib_get_err_str(status));
		osm_port_get_lid_range_ho(p_port, &min_lid_ho, &max_lid_ho);
		OSM_LOG(sm->p_log, OSM_LOG_INFO,
			"Discovered new port with GUID:0x%016" PRIx64
			" LID range [%u,%u] of node: %s\n",
			cl_ntoh64(port_gid.unicast.interface_id),
			min_lid_ho, max_lid_ho,
			p_port->p_node ? p_port->p_node->
			print_desc : "UNKNOWN");

		p_port->is_new = 0;
	}
	CL_PLOCK_RELEASE(sm->p_lock);

	OSM_LOG_EXIT(sm->p_log);
}
Exemple #18
0
/**********************************************************************
 * Fill in the array of port_attr with all available ports on ALL the
 * avilable CAs on this machine.
 * ALSO -
 * Update the vendor object list of ca_info structs
 **********************************************************************/
ib_api_status_t
osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
			     IN ib_port_attr_t * const p_attr_array,
			     IN uint32_t * const p_num_ports)
{
	ib_api_status_t status;

	uint32_t ca;
	uint32_t ca_count = 0;
	uint32_t port_count = 0;
	uint8_t port_num;
	uint32_t total_ports = 0;
	VAPI_hca_id_t *p_ca_ids = NULL;
	osm_ca_info_t *p_ca_infos = NULL;
	uint32_t attr_array_sz = *p_num_ports;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_vend);

	/* determine the number of CA's */
	status = __osm_vendor_get_ca_ids(p_vend, &p_ca_ids, &ca_count);
	if (status != IB_SUCCESS) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_get_all_port_attr: ERR 3D13: "
			"Fail to get CA Ids.\n");
		goto Exit;
	}

	/* Allocate an array big enough to hold the ca info objects */
	p_ca_infos = malloc(ca_count * sizeof(osm_ca_info_t));
	if (p_ca_infos == NULL) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_get_all_port_attr: ERR 3D14: "
			"Unable to allocate CA information array.\n");
		goto Exit;
	}

	memset(p_ca_infos, 0, ca_count * sizeof(osm_ca_info_t));

	/*
	 * For each CA, retrieve the CA info attributes
	 */
	for (ca = 0; ca < ca_count; ca++) {
		status =
		    __osm_ca_info_init(p_vend, p_ca_ids[ca], &p_ca_infos[ca]);
		if (status != IB_SUCCESS) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_vendor_get_all_port_attr: ERR 3D15: "
				"Unable to initialize CA Info object (%s).\n",
				ib_get_err_str(status));
			goto Exit;
		}
		total_ports += p_ca_infos[ca].p_attr->num_ports;
	}

	*p_num_ports = total_ports;
	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
		"osm_vendor_get_all_port_attr: total ports:%u \n", total_ports);

	/*
	 * If the user supplied enough storage, return the port guids,
	 * otherwise, return the appropriate error.
	 */
	if (attr_array_sz >= total_ports) {
		for (ca = 0; ca < ca_count; ca++) {
			uint32_t num_ports;

			num_ports = p_ca_infos[ca].p_attr->num_ports;

			for (port_num = 0; port_num < num_ports; port_num++) {
				p_attr_array[port_count] =
				    *__osm_ca_info_get_port_attr_ptr(&p_ca_infos
								     [ca],
								     port_num);
				port_count++;
			}
		}
	} else {
		status = IB_INSUFFICIENT_MEMORY;
		goto Exit;
	}

	status = IB_SUCCESS;

Exit:
	if (p_ca_ids)
		free(p_ca_ids);

	if (p_ca_infos) {
		osm_ca_info_destroy(p_vend, p_ca_infos, ca_count);
	}

	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
Exemple #19
0
ib_api_status_t
osm_vendor_get_all_port_attr(IN osm_vendor_t * const p_vend,
			     IN ib_port_attr_t * const p_attr_array,
			     IN uint32_t * const p_num_ports)
{
	ib_api_status_t status;

	uint32_t ca;
	uintn_t ca_count;
	uint32_t port_count = 0;
	uint8_t port_num;
	uint32_t total_ports = 0;
	ib_net64_t *p_ca_guid = NULL;
	osm_ca_info_t *p_ca_info;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_vend);
	CL_ASSERT(p_vend->p_ca_info == NULL);

	/*
	   1) Determine the number of CA's
	   2) Allocate an array big enough to hold the ca info objects.
	   3) Call again to retrieve the guids.
	 */
	status = __osm_vendor_get_ca_guids(p_vend, &p_ca_guid, &ca_count);

	p_vend->p_ca_info = malloc(ca_count * sizeof(*p_vend->p_ca_info));
	if (p_vend->p_ca_info == NULL) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_get_all_port_attr: ERR 3B11: "
			"Unable to allocate CA information array.\n");
		goto Exit;
	}

	memset(p_vend->p_ca_info, 0, ca_count * sizeof(*p_vend->p_ca_info));
	p_vend->ca_count = ca_count;

	/*
	   For each CA, retrieve the port info attributes
	 */
	for (ca = 0; ca < ca_count; ca++) {
		p_ca_info = &p_vend->p_ca_info[ca];

		status = __osm_ca_info_init(p_vend, p_ca_info, p_ca_guid[ca]);

		if (status != IB_SUCCESS) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_vendor_get_all_port_attr: ERR 3B12: "
				"Unable to initialize CA Info object (%s).\n",
				ib_get_err_str(status));
		}

		total_ports += osm_ca_info_get_num_ports(p_ca_info);
	}

	/*
	   If the user supplied enough storage, return the port guids,
	   otherwise, return the appropriate error.
	 */
	if (*p_num_ports >= total_ports) {
		for (ca = 0; ca < ca_count; ca++) {
			uint32_t num_ports;

			p_ca_info = &p_vend->p_ca_info[ca];

			num_ports = osm_ca_info_get_num_ports(p_ca_info);

			for (port_num = 0; port_num < num_ports; port_num++) {
				p_attr_array[port_count] =
				    *__osm_ca_info_get_port_attr_ptr(p_ca_info,
								     port_num);
				port_count++;
			}
		}
	} else {
		status = IB_INSUFFICIENT_MEMORY;
	}

	*p_num_ports = total_ports;

Exit:
	if (p_ca_guid)
		free(p_ca_guid);

	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
static void ucast_mgr_set_fwd_top(IN cl_map_item_t * p_map_item,
				  IN void *cxt)
{
	osm_ucast_mgr_t *p_mgr = cxt;
	osm_switch_t * p_sw = (osm_switch_t *) p_map_item;
	osm_node_t *p_node;
	osm_physp_t *p_physp;
	osm_dr_path_t *p_path;
	osm_madw_context_t context;
	ib_api_status_t status;
	ib_switch_info_t si;
	boolean_t set_swinfo_require = FALSE;
	uint16_t lin_top;
	uint8_t life_state;

	CL_ASSERT(p_mgr);

	OSM_LOG_ENTER(p_mgr->p_log);

	CL_ASSERT(p_sw && p_sw->max_lid_ho);

	p_node = p_sw->p_node;

	CL_ASSERT(p_node);

	if (p_mgr->max_lid < p_sw->max_lid_ho)
		p_mgr->max_lid = p_sw->max_lid_ho;

	p_physp = osm_node_get_physp_ptr(p_node, 0);

	CL_ASSERT(p_physp);

	p_path = osm_physp_get_dr_path_ptr(p_physp);

	/*
	   Set the top of the unicast forwarding table.
	 */
	si = p_sw->switch_info;
	lin_top = cl_hton16(p_sw->max_lid_ho);
	if (lin_top != si.lin_top) {
		set_swinfo_require = TRUE;
		si.lin_top = lin_top;
		context.si_context.lft_top_change = TRUE;
	} else
		context.si_context.lft_top_change = FALSE;

	life_state = si.life_state;
	ib_switch_info_set_life_time(&si, p_mgr->p_subn->opt.packet_life_time);

	if (life_state != si.life_state)
		set_swinfo_require = TRUE;

	if (set_swinfo_require) {
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
			"Setting switch FT top to LID %u\n", p_sw->max_lid_ho);

		context.si_context.light_sweep = FALSE;
		context.si_context.node_guid = osm_node_get_node_guid(p_node);
		context.si_context.set_method = TRUE;

		status = osm_req_set(p_mgr->sm, p_path, (uint8_t *) & si,
				     sizeof(si), IB_MAD_ATTR_SWITCH_INFO,
				     0, FALSE,
				     ib_port_info_get_m_key(&p_physp->port_info),
				     CL_DISP_MSGID_NONE, &context);

		if (status != IB_SUCCESS)
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A06: "
				"Sending SwitchInfo attribute failed (%s)\n",
				ib_get_err_str(status));
	}

	OSM_LOG_EXIT(p_mgr->p_log);
}
Exemple #21
0
/**********************************************************************
 Sweeps the node 1 hop away.
 This sets off a "chain reaction" that causes discovery of the subnet.
 Used when there is suspicion that something on the subnet has changed.
**********************************************************************/
static ib_api_status_t state_mgr_sweep_hop_1(IN osm_sm_t * sm)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_bind_handle_t h_bind;
	osm_madw_context_t context;
	osm_node_t *p_node;
	osm_port_t *p_port;
	osm_physp_t *p_physp;
	osm_dr_path_t *p_dr_path;
	osm_dr_path_t hop_1_path;
	ib_net64_t port_guid;
	uint8_t port_num;
	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
	uint8_t num_ports;
	osm_physp_t *p_ext_physp;

	OSM_LOG_ENTER(sm->p_log);

	/*
	 * First, get our own port and node objects.
	 */
	port_guid = sm->p_subn->sm_port_guid;

	CL_ASSERT(port_guid);

	/* Set the in_sweep_hop_0 flag in subn to be FALSE.
	 * This will indicate the sweeping to continue beyond the
	 * the current node.
	 * This is relevant for the case of SM on switch, since in the
	 * switch info we need to signal that the sweeping should
	 * continue through the switch. */
	sm->p_subn->in_sweep_hop_0 = FALSE;

	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
	if (!p_port) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: "
			"No SM port object\n");
		status = IB_ERROR;
		goto Exit;
	}

	p_node = p_port->p_node;
	CL_ASSERT(p_node);

	port_num = ib_node_info_get_local_port_num(&p_node->node_info);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Probing hop 1 on local port %u\n", port_num);

	p_physp = osm_node_get_physp_ptr(p_node, port_num);

	CL_ASSERT(p_physp);

	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
	h_bind = osm_dr_path_get_bind_handle(p_dr_path);

	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);

	memset(path_array, 0, sizeof(path_array));
	/* the hop_1 operations depend on the type of our node.
	 * Currently - legal nodes that can host SM are SW and CA */
	switch (osm_node_get_type(p_node)) {
	case IB_NODE_TYPE_CA:
	case IB_NODE_TYPE_ROUTER:
		memset(&context, 0, sizeof(context));
		context.ni_context.node_guid = osm_node_get_node_guid(p_node);
		context.ni_context.port_num = port_num;

		path_array[1] = port_num;

		osm_dr_path_init(&hop_1_path, h_bind, 1, path_array);
		status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0,
				     CL_DISP_MSGID_NONE, &context);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: "
				"Request for NodeInfo failed (%s)\n",
				ib_get_err_str(status));
		break;

	case IB_NODE_TYPE_SWITCH:
		/* Need to go over all the ports of the switch, and send a
		 * node_info from them. This doesn't include the port 0 of the
		 * switch, which hosts the SM.
		 * Note: We'll send another switchInfo on port 0, since if no
		 * ports are connected, we still want to get some response, and
		 * have the subnet come up.
		 */
		num_ports = osm_node_get_num_physp(p_node);
		for (port_num = 1; port_num < num_ports; port_num++) {
			/* go through the port only if the port is not DOWN */
			p_ext_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (p_ext_physp && ib_port_info_get_port_state
			    (&(p_ext_physp->port_info)) > IB_LINK_DOWN) {
				memset(&context, 0, sizeof(context));
				context.ni_context.node_guid =
				    osm_node_get_node_guid(p_node);
				context.ni_context.port_num = port_num;

				path_array[1] = port_num;
				osm_dr_path_init(&hop_1_path, h_bind, 1,
						 path_array);
				status = osm_req_get(sm, &hop_1_path,
						     IB_MAD_ATTR_NODE_INFO, 0,
						     CL_DISP_MSGID_NONE,
						     &context);
				if (status != IB_SUCCESS)
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
						"ERR 3312: "
						"Request for NodeInfo failed (%s)\n",
						ib_get_err_str(status));
			}
		}
		break;

	default:
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 3313: Unknown node type %d (%s)\n",
			osm_node_get_type(p_node), p_node->print_desc);
	}

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return status;
}
Exemple #22
0
int main(int argc, char *argv[])
{
    static osmtest_t osm_test;
    osmtest_opt_t opt = { 0 };
    ib_net64_t guid = 0;
    uint16_t max_lid = 100;
    ib_api_status_t status;
    uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO;
    int32_t vendor_debug = 0;
    char flow_name[64];
    uint32_t next_option;
    const char *const short_option = "f:l:m:M:d:g:s:t:i:pcvVh";

    /*
     * In the array below, the 2nd parameter specified the number
     * of arguments as follows:
     * 0: no arguments
     * 1: argument
     * 2: optional
     */
    const struct option long_option[] = {
        {"create", 0, NULL, 'c'},
        {"debug", 1, NULL, 'd'},
        {"flow", 1, NULL, 'f'},
        {"wait", 1, NULL, 'w'},
        {"inventory", 1, NULL, 'i'},
        {"max_lid", 1, NULL, 'm'},
        {"guid", 2, NULL, 'g'},
        {"port", 0, NULL, 'p'},
        {"help", 0, NULL, 'h'},
        {"stress", 1, NULL, 's'},
        {"Multicast_Mode", 1, NULL, 'M'},
        {"timeout", 1, NULL, 't'},
        {"verbose", 0, NULL, 'v'},
        {"log_file", 1, NULL, 'l'},
        {"vf", 1, NULL, 'x'},
        {"V", 0, NULL, 'V'},

        {NULL, 0, NULL, 0}	/* Required at end of array */
    };

    /* Make sure that the opensm, complib and osmtest were compiled using
       same modes (debug/free) */
    if (osm_is_debug() != cl_is_debug() || osm_is_debug() != osmt_is_debug()
            || osmt_is_debug() != cl_is_debug()) {
        fprintf(stderr,
                "-E- OpenSM, Complib and OsmTest were compiled using different modes\n");
        fprintf(stderr,
                "-E- OpenSM debug:%d Complib debug:%d OsmTest debug:%d \n",
                osm_is_debug(), cl_is_debug(), osmt_is_debug());
        exit(1);
    }

    opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC;
    opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC;
    opt.retry_count = OSMT_DEFAULT_RETRY_COUNT;
    opt.force_log_flush = FALSE;
    opt.stress = 0;
    opt.log_file = NULL;
    opt.create = FALSE;
    opt.mmode = 1;
    opt.ignore_path_records = FALSE;	/*  Do path Records too */
    opt.flow = OSMT_FLOW_ALL;	/*  run all validation tests */
    strcpy(flow_name, "All Validations");
    strcpy(opt.file_name, "osmtest.dat");

    printf("\nCommand Line Arguments\n");
    do {
        next_option = getopt_long_only(argc, argv, short_option,
                                       long_option, NULL);
        switch (next_option) {
        case 'c':
            /*
             * Create the inventory file.
             */
            opt.create = TRUE;
            printf("\tCreating inventory file\n");
            break;

        case 'i':
            /*
             * Specifies inventory file name.
             */
            if (strlen(optarg) > OSMTEST_FILE_PATH_MAX)
                printf
                ("\nError: path name too long (ignored)\n");
            else
                strcpy(opt.file_name, optarg);

            printf("\tFile = %s\n", opt.file_name);
            break;

        case 'f':
            /*
             * Specifies Flow .
             */
            if (strlen(optarg) > OSMTEST_FILE_PATH_MAX)
                printf
                ("\nError: path name too long (ignored)\n");
            else
                strcpy(flow_name, optarg);

            if (!strcmp("c", optarg)) {
                strcpy(flow_name, "Create Inventory");
                opt.flow = OSMT_FLOW_CREATE_INVENTORY;
            } else if (!strcmp("v", optarg)) {
                strcpy(flow_name, "Validate Inventory");
                opt.flow = OSMT_FLOW_VALIDATE_INVENTORY;
            } else if (!strcmp("s", optarg)) {
                strcpy(flow_name, "Services Registration");
                opt.flow = OSMT_FLOW_SERVICE_REGISTRATION;
            } else if (!strcmp("e", optarg)) {
                strcpy(flow_name, "Event Forwarding");
                opt.flow = OSMT_FLOW_EVENT_FORWARDING;
            } else if (!strcmp("f", optarg)) {
                strcpy(flow_name, "Stress SA");
                opt.flow = OSMT_FLOW_STRESS_SA;
            } else if (!strcmp("m", optarg)) {
                strcpy(flow_name, "Multicast");
                opt.flow = OSMT_FLOW_MULTICAST;
            } else if (!strcmp("q", optarg)) {
                strcpy(flow_name, "QoS: VLArb and SLtoVL");
                opt.flow = OSMT_FLOW_QOS;
            } else if (!strcmp("t", optarg)) {
                strcpy(flow_name, "Trap 64/65");
                opt.flow = OSMT_FLOW_TRAP;
            } else if (!strcmp("a", optarg)) {
                strcpy(flow_name, "All Validations");
                opt.flow = OSMT_FLOW_ALL;
            } else {
                printf("\nError: unknown flow %s\n", flow_name);
                exit(2);
            }
            break;

        case 'w':
            /*
             * Specifies trap 64/65 wait time
             */
            CL_ASSERT(strtol(optarg, NULL, 0) < 0x100);
            opt.wait_time = (uint8_t) strtol(optarg, NULL, 0);
            printf("\tTrap 64/65 wait time = %d\n", opt.wait_time);
            break;

        case 'm':
            /*
             * Specifies the max LID to search for during exploration.
             */
            max_lid = atoi(optarg);
            printf("\tMAX-LID %u\n", max_lid);
            break;

        case 'g':
            /*
             * Specifies port guid with which to bind.
             */
            guid = cl_hton64(strtoull(optarg, NULL, 16));
            printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(guid));
            break;

        case 'p':
            /*
             * Display current port guids
             */
            guid = INVALID_GUID;
            break;

        case 't':
            /*
             * Specifies transaction timeout.
             */
            opt.transaction_timeout = strtol(optarg, NULL, 0);
            printf("\tTransaction timeout = %d\n",
                   opt.transaction_timeout);
            break;

        case 'l':
            opt.log_file = optarg;
            printf("\tLog File:%s\n", opt.log_file);
            break;

        case 'v':
            /*
             * Increases log verbosity.
             */
            log_flags = (log_flags << 1) | 1;
            printf("\tVerbose option -v (log flags = 0x%X)\n",
                   log_flags);
            break;

        case 'V':
            /*
             * Specifies maximum log verbosity.
             */
            log_flags = 0xFFFFFFFF;
            opt.force_log_flush = TRUE;
            printf("\tEnabling maximum log verbosity\n");
            break;

        case 's':
            /*
             * Perform stress test.
             */
            opt.stress = strtol(optarg, NULL, 0);
            printf("\tStress test enabled: ");
            switch (opt.stress) {
            case 1:
                printf("Small SA queries\n");
                break;
            case 2:
                printf("Large SA queries\n");
                break;
            case 3:
                printf("Large Path Record SA queries\n");
                break;
            default:
                printf("Unknown value %u (ignored)\n",
                       opt.stress);
                opt.stress = 0;
                break;
            }
            break;

        case 'M':
            /*
             * Perform multicast test.
             */
            opt.mmode = strtol(optarg, NULL, 0);
            printf("\tMulticast test enabled: ");
            switch (opt.mmode) {
            case 1:
                printf
                ("Short MC Flow - single mode (default)\n");
                break;
            case 2:
                printf("Short MC Flow - multiple mode\n");
                break;
            case 3:
                printf("Long MC Flow - single mode\n");
                break;
            case 4:
                printf("Long MC Flow - multiple mode\n");
                break;
            default:
                printf("Unknown value %u (ignored)\n",
                       opt.stress);
                opt.mmode = 0;
                break;
            }
            break;

        case 'd':
            /*
             * Debug Options
             */
            printf("\tDebug Option: ");
            switch (strtol(optarg, NULL, 0)) {
            case 1:
                printf("Ignore Path Records\n");
                opt.ignore_path_records = TRUE;
                break;
            case 2:
                printf("Force Log Flush\n");
                opt.force_log_flush = TRUE;
                break;
            case 3:
            /* Used to be memory tracking */
            default:
                printf("Unknown value %ld (ignored)\n",
                       strtol(optarg, NULL, 0));
                break;
            }
            break;

        case 'h':
            show_usage();
            return 0;

        case 'x':
            log_flags = strtol(optarg, NULL, 0);
            printf
            ("\t\t\t\tVerbose option -vf (log flags = 0x%X)\n",
             log_flags);
            break;

        case -1:
            printf("Done with args\n");
            break;

        default:
            show_usage();
            return 1;
        }

    }
    while (next_option != -1);

    printf("\tFlow = %s\n", flow_name);

    if (vendor_debug)
        osm_vendor_set_debug(osm_test.p_vendor, vendor_debug);

    complib_init();

    status = osmtest_init(&osm_test, &opt, (osm_log_level_t) log_flags);
    if (status != IB_SUCCESS) {
        printf("\nError from osmtest_init: %s\n",
               ib_get_err_str(status));
        goto Exit;
    }
    if (cl_hton64(guid) == cl_hton64(INVALID_GUID)) {
        print_all_guids(&osm_test);
        complib_exit();
        return (status);
    }

    /*
       If the user didn't specify a GUID on the command line,
       then get a port GUID value with which to bind.
     */
    if (guid == 0 && !(guid = get_port_guid(&osm_test, guid))) {
        printf("\nError: port guid 0x%" PRIx64 " not found\n", guid);
        goto Exit;
    }

    /*
     * Guid may be zero going into this function if the user
     * hasn't specified a binding port on the command line.
     */
    status = osmtest_bind(&osm_test, max_lid, guid);
    if (status != IB_SUCCESS)
        exit(status);

    status = osmtest_run(&osm_test);
    if (status != IB_SUCCESS) {
        printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name);
    } else {
        printf("OSMTEST: TEST \"%s\" PASS\n", flow_name);
    }
    osmtest_destroy(&osm_test);

    complib_exit();

Exit:
    return (status);
}
static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr,
			 IN uint16_t block_id_ho)
{
	osm_madw_context_t context;
	osm_dr_path_t *p_path;
	osm_physp_t *p_physp;
	ib_api_status_t status;

	/*
	   Send linear forwarding table blocks to the switch
	   as long as the switch indicates it has blocks needing
	   configuration.
	 */
	if (!p_sw->new_lft) {
		/* any routing should provide the new_lft */
		CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
			  p_mgr->cache_valid && !p_sw->need_update);
		return -1;
	}

	p_physp = osm_node_get_physp_ptr(p_sw->p_node, 0);
	if (!p_physp)
		return -1;

	p_path = osm_physp_get_dr_path_ptr(p_physp);

	context.lft_context.node_guid = osm_node_get_node_guid(p_sw->p_node);
	context.lft_context.set_method = TRUE;

	if (!p_sw->need_update && !p_mgr->p_subn->need_update &&
	    !memcmp(p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
		    p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE,
		    IB_SMP_DATA_SIZE))
		return 0;

	/*
	 * Zero the stored LFT block, so in case the MAD will end up
	 * with error, we will resend it in the next sweep.
	 */
	memset(p_sw->lft + block_id_ho * IB_SMP_DATA_SIZE, 0,
	       IB_SMP_DATA_SIZE);

	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
		"Writing FT block %u to switch 0x%" PRIx64 "\n", block_id_ho,
		cl_ntoh64(context.lft_context.node_guid));

	status = osm_req_set(p_mgr->sm, p_path,
			     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
			     IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL,
			     cl_hton32(block_id_ho), FALSE,
			     ib_port_info_get_m_key(&p_physp->port_info),
			     CL_DISP_MSGID_NONE, &context);

	if (status != IB_SUCCESS) {
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A10: "
			"Sending linear fwd. tbl. block failed (%s)\n",
			ib_get_err_str(status));
		return -1;
	}

	return 0;
}
Exemple #24
0
osm_bind_handle_t
osm_vendor_bind(IN osm_vendor_t * const p_vend,
		IN osm_bind_info_t * const p_user_bind,
		IN osm_mad_pool_t * const p_mad_pool,
		IN osm_vend_mad_recv_callback_t mad_recv_callback,
		IN osm_vend_mad_send_err_callback_t send_err_callback,
		IN void *context)
{
	ib_net64_t port_guid;
	osm_al_bind_info_t *p_bind = 0;
	ib_api_status_t status;
	ib_qp_create_t qp_create;
	ib_mad_svc_t mad_svc;
	ib_av_attr_t av;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_user_bind);
	CL_ASSERT(p_mad_pool);
	CL_ASSERT(mad_recv_callback);
	CL_ASSERT(send_err_callback);

	port_guid = p_user_bind->port_guid;

	osm_log(p_vend->p_log, OSM_LOG_INFO,
		"osm_vendor_bind: "
		"Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));

	if (p_vend->h_ca == 0) {
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
			"osm_vendor_bind: "
			"Opening CA that owns port 0x%" PRIx64 ".\n",
			port_guid);

		status = __osm_vendor_open_ca(p_vend, port_guid);
		if (status != IB_SUCCESS) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_vendor_bind: ERR 3B17: "
				"Unable to Open CA (%s).\n",
				ib_get_err_str(status));
			goto Exit;
		}
	}

	p_bind = malloc(sizeof(*p_bind));
	if (p_bind == NULL) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_bind: ERR 3B18: "
			"Unable to allocate internal bind object.\n");
		goto Exit;
	}

	memset(p_bind, 0, sizeof(*p_bind));
	p_bind->p_vend = p_vend;
	p_bind->client_context = context;
	p_bind->port_num = osm_vendor_get_port_num(p_vend, port_guid);
	p_bind->rcv_callback = mad_recv_callback;
	p_bind->send_err_callback = send_err_callback;
	p_bind->p_osm_pool = p_mad_pool;

	CL_ASSERT(p_bind->port_num);

	/*
	   Get the proper QP.
	 */
	memset(&qp_create, 0, sizeof(qp_create));

	switch (p_user_bind->mad_class) {
	case IB_MCLASS_SUBN_LID:
	case IB_MCLASS_SUBN_DIR:
		qp_create.qp_type = IB_QPT_QP0_ALIAS;
		break;

	case IB_MCLASS_SUBN_ADM:
	default:
		qp_create.qp_type = IB_QPT_QP1_ALIAS;
		break;
	}

	qp_create.sq_depth = p_user_bind->send_q_size;
	qp_create.rq_depth = p_user_bind->recv_q_size;
	qp_create.sq_sge = OSM_AL_SQ_SGE;
	qp_create.rq_sge = OSM_AL_RQ_SGE;

	status = ib_get_spl_qp(p_vend->h_pd,
			       port_guid,
			       &qp_create,
			       p_bind,
			       __osm_al_err_callback,
			       &p_bind->pool_key, &p_bind->h_qp);

	if (status != IB_SUCCESS) {
		free(p_bind);
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_bind: ERR 3B19: "
			"Unable to get QP handle (%s).\n",
			ib_get_err_str(status));
		goto Exit;
	}

	CL_ASSERT(p_bind->h_qp);
	CL_ASSERT(p_bind->pool_key);

	memset(&mad_svc, 0, sizeof(mad_svc));

	mad_svc.mad_svc_context = p_bind;
	mad_svc.pfn_mad_send_cb = __osm_al_send_callback;
	mad_svc.pfn_mad_recv_cb = __osm_al_rcv_callback;
	mad_svc.mgmt_class = p_user_bind->mad_class;
	mad_svc.mgmt_version = p_user_bind->class_version;
	mad_svc.support_unsol = p_user_bind->is_responder;
	mad_svc.method_array[IB_MAD_METHOD_GET] = TRUE;
	mad_svc.method_array[IB_MAD_METHOD_SET] = TRUE;
	mad_svc.method_array[IB_MAD_METHOD_DELETE] = TRUE;
	mad_svc.method_array[IB_MAD_METHOD_TRAP] = TRUE;
	mad_svc.method_array[IB_MAD_METHOD_GETTABLE] = TRUE;

	status = ib_reg_mad_svc(p_bind->h_qp, &mad_svc, &p_bind->h_svc);

	if (status != IB_SUCCESS) {
		free(p_bind);
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_bind: ERR 3B21: "
			"Unable to register QP0 MAD service (%s).\n",
			ib_get_err_str(status));
		goto Exit;
	}

	__osm_vendor_init_av(p_bind, &av);

	status = ib_create_av(p_vend->h_pd, &av, &p_bind->h_dr_av);
	if (status != IB_SUCCESS) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_bind: ERR 3B22: "
			"Unable to create address vector (%s).\n",
			ib_get_err_str(status));

		goto Exit;
	}

	if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
			"osm_vendor_bind: "
			"Allocating av handle %p.\n", p_bind->h_dr_av);
	}

Exit:
	OSM_LOG_EXIT(p_vend->p_log);
	return ((osm_bind_handle_t) p_bind);
}
/*
 * Run a complete inform info test flow:
 * - try to unregister inform info (should fail)
 * - register an inform info
 * - try to unregister inform info (should succeed)
 * - register an inform info
 * - send a trap - sleep
 * - check that a Report(Notice) arrived that matches the sent trap
 *
 */
ib_api_status_t osmt_run_inform_info_flow(IN osmtest_t * const p_osmt)
{
	ib_inform_info_t inform_info;
	ib_api_status_t status;
	osmt_qp_ctx_t qp_ctx;

	OSM_LOG_ENTER(&p_osmt->log);

	/* bind the QP */
	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
	if (status != IB_SUCCESS) {
		goto Exit;
	}

	/* init the inform info */
	osmt_init_inform_info(p_osmt, &inform_info);

	/* first try to unsubscribe */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);
	/* WAS IB_REMOTE_ERROR */
	if (status != IB_REMOTE_ERROR) {
		if (status != IB_SUCCESS) {
			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
				"Error during UnSubscribe: (%s)\n",
				ib_get_err_str(status));
			goto Exit;
		} else {
			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
				"Expected Failure to UnSubscribe non existing InformInfo\n");
			status = IB_ERROR;
			goto Exit;
		}
	}

	/* send the inform info registration */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
	if (status != IB_SUCCESS) {
		goto Exit;
	}

	/* send a trap through QP0 and wait on QPN */
	status = osmt_send_trap_wait_for_forward(p_osmt, &qp_ctx);
	if (status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Error during Send Trap and Wait For Report: (%s)\n",
			ib_get_err_str(status));
		goto Exit;
	}

	/* try to unsubscribe for cleanup */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);

	if (status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Error during UnSubscribe: (%s)\n",
			ib_get_err_str(status));
		goto Exit;
	} else {
		if (status == IB_REMOTE_ERROR) {
			OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
				"Remote Error during UnSubscribe\n");
			status = IB_ERROR;
			goto Exit;
		}
	}

Exit:
	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
	OSM_LOG_EXIT(&p_osmt->log);
	return status;
}
/*
 * Run a complete inform info test flow:
 * - try to unregister inform info (should fail)
 * - register an inform info
 * - try to unregister inform info (should succeed)
 * - register an inform info
 * - send a trap - sleep
 * - check that a Report(Notice) arrived that match the sent one
 *
 */
ib_api_status_t osmt_run_trap64_65_flow(IN osmtest_t * const p_osmt)
{
	ib_inform_info_t inform_info;
	ib_api_status_t status;
	osmt_qp_ctx_t qp_ctx;

	OSM_LOG_ENTER(&p_osmt->log);

	/* bind the QP */
	status = osmt_bind_inform_qp(p_osmt, &qp_ctx);
	if (status != IB_SUCCESS) {
		goto Exit;
	}

	/* init the inform info */
	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(64), &inform_info);

	/* send the inform info registration */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
	if (status != IB_SUCCESS) {
		goto Exit;
	}

  /*--------------------- PREP -------------------------*/
	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to receive the report */
					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
			"Error posting recv bufs for trap 64\n");
		status = IB_ERROR;
		goto Exit;
	}

	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 64\n");

	/* init the inform info */
	osmt_init_inform_info_by_trap(p_osmt, cl_hton16(65), &inform_info);

	/* send the inform info registration */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 1);
	if (status != IB_SUCCESS) {
		goto Exit;
	}

  /*--------------------- PREP -------------------------*/
	if (osmt_mtl_mad_post_recv_bufs(&qp_ctx.qp_bind_hndl, qp_ctx.p_recv_buf, 1,	/* we need to receive the report */
					GRH_LEN + MAD_BLOCK_SIZE, 1) != 1) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "ERR 0127: "
			"Error posting recv bufs for trap 65\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(&p_osmt->log, OSM_LOG_DEBUG, "Posted recv bufs for trap 65\n");

	/* Sleep for x seconds in order to allow external script trap generation */
#if 0
	sleep(p_osmt->opt.wait_time);
#endif

	/* wait for a trap on QPN */
	status = osmt_trap_wait(p_osmt, &qp_ctx);
	if (status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Error during Send Trap and Wait For Report: (%s)\n",
			ib_get_err_str(status));
		goto Exit;
	}

	/* try to unsubscribe for cleanup */
	status = osmt_reg_unreg_inform_info(p_osmt, &qp_ctx, &inform_info, 0);

	if (status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Error during UnSubscribe: (%s)\n",
			ib_get_err_str(status));
		goto Exit;
	}

Exit:
	osmt_unbind_inform_qp(p_osmt, &qp_ctx);
	OSM_LOG_EXIT(&p_osmt->log);
	return status;
}
Exemple #27
0
/*****************************************************************************
 This routine needs to be invoked on every send - since the SM LID and Local
 lid might change. To do that without any major perfoermance impact we cache
 the results and time they were obtained. Refresh only twice a minute.
 To avoid the need to use statics and risk a race - we require the refresh time
 to be stored in the context of the results. Also this coveres cases were
 we query for multiple guids.
 *****************************************************************************/
ib_api_status_t
__osmv_get_lid_and_sm_lid_by_port_guid(IN osm_vendor_t * const p_vend,
				       IN ib_net64_t port_guid,
				       IN OUT uint64_t * p_lids_update_time_sec,
				       OUT uint16_t * lid,
				       OUT uint16_t * sm_lid)
{

	ib_api_status_t status;
	ib_port_attr_t *p_attr_array;
	uint32_t num_ports;
	uint32_t port_num;

	OSM_LOG_ENTER(p_vend->p_log);

	/* use prevous values if current time is close enough to previous query */
	if (cl_get_time_stamp_sec() <= *p_lids_update_time_sec + 30) {
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
			"__osmv_get_lid_and_sm_lid_by_port_guid: "
			"Using previously stored lid:0x%04x sm_lid:0x%04x\n",
			*lid, *sm_lid);
		status = IB_SUCCESS;
		goto Exit;
	}

	/* obtain the number of available ports */
	num_ports = 0;
	status = osm_vendor_get_all_port_attr(p_vend, NULL, &num_ports);
	if (status != IB_INSUFFICIENT_MEMORY) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0503: "
			"expected to get the IB_INSUFFICIENT_MEMORY but got: %s\n",
			ib_get_err_str(status)
		    );
		status = IB_ERROR;
		goto Exit;
	}

	osm_log(p_vend->p_log, OSM_LOG_DEBUG,
		"__osmv_get_lid_and_sm_lid_by_port_guid: "
		"Found total of %u ports. Looking for guid:0x%016" PRIx64 "\n",
		num_ports, cl_ntoh64(port_guid)
	    );

	/* allocate the attributes */
	p_attr_array =
	    (ib_port_attr_t *) malloc(sizeof(ib_port_attr_t) * num_ports);

	/* obtain the attributes */
	status = osm_vendor_get_all_port_attr(p_vend, p_attr_array, &num_ports);
	if (status != IB_SUCCESS) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"__osmv_get_lid_and_sm_lid_by_port_guid: ERR 0504: "
			"Fail to get port attributes (error: %s)\n",
			ib_get_err_str(status)
		    );
		free(p_attr_array);
		goto Exit;
	}

	status = IB_ERROR;
	/* find the port requested in the list */
	for (port_num = 0; (port_num < num_ports) && (status == IB_ERROR);
	     port_num++) {
		if (p_attr_array[port_num].port_guid == port_guid) {
			*lid = p_attr_array[port_num].lid;
			*sm_lid = p_attr_array[port_num].sm_lid;
			*p_lids_update_time_sec = cl_get_time_stamp_sec();
			status = IB_SUCCESS;
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
				"__osmv_get_lid_and_sm_lid_by_port_guid: "
				"Found guid:0x%016" PRIx64 " with idx:%d\n",
				cl_ntoh64(port_guid), port_num);
		}
	}

	free(p_attr_array);

Exit:
	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
Exemple #28
0
ib_api_status_t
osm_vendor_send(IN osm_bind_handle_t h_bind,
		IN osm_madw_t * const p_madw, IN boolean_t const resp_expected)
{
	osm_al_bind_info_t *const p_bind = h_bind;
	osm_vendor_t *const p_vend = p_bind->p_vend;
	osm_vend_wrap_t *const p_vw = osm_madw_get_vend_ptr(p_madw);
	osm_mad_addr_t *const p_mad_addr = osm_madw_get_mad_addr_ptr(p_madw);
	ib_mad_t *const p_mad = osm_madw_get_mad_ptr(p_madw);
	ib_api_status_t status;
	ib_mad_element_t *p_elem;
	ib_av_attr_t av;

	OSM_LOG_ENTER(p_vend->p_log);

	CL_ASSERT(p_vw->h_bind == h_bind);
	CL_ASSERT(p_vw->p_elem);

	p_elem = p_vw->p_elem;

	/*
	   If a response is expected to this MAD, then preallocate
	   a mad wrapper to contain the wire MAD received in the
	   response.  Allocating a wrapper here allows for easier
	   failure paths than after we already received the wire mad.
	 */
	if (resp_expected) {
		p_vw->p_resp_madw =
		    osm_mad_pool_get_wrapper_raw(p_bind->p_osm_pool);
		if (p_vw->p_resp_madw == NULL) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_vendor_send: ERR 3B27: "
				"Unable to allocate MAD wrapper.\n");
			status = IB_INSUFFICIENT_RESOURCES;
			goto Exit;
		}
	} else
		p_vw->p_resp_madw = NULL;

	/*
	   For all sends other than directed route SM MADs,
	   acquire an address vector for the destination.
	 */
	if (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR) {
		memset(&av, 0, sizeof(av));
		av.port_num = p_bind->port_num;
		av.dlid = p_mad_addr->dest_lid;
		av.static_rate = p_mad_addr->static_rate;
		av.path_bits = p_mad_addr->path_bits;

		if ((p_mad->mgmt_class != IB_MCLASS_SUBN_LID) &&
		    (p_mad->mgmt_class != IB_MCLASS_SUBN_DIR)) {
			av.sl = p_mad_addr->addr_type.gsi.service_level;

			if (p_mad_addr->addr_type.gsi.global_route) {
				av.grh_valid = TRUE;
				/* ANIL */
				/* av.grh = p_mad_addr->addr_type.gsi.grh_info; */
			}
		}

		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
				"osm_vendor_send: "
				"av.port_num 0x%X, "
				"av.dlid 0x%X, "
				"av.static_rate   %d, "
				"av.path_bits %d.\n",
				av.port_num, cl_ntoh16(av.dlid),
				av.static_rate, av.path_bits);
		}

		status = ib_create_av(p_vend->h_pd, &av, &p_vw->h_av);
		if (status != IB_SUCCESS) {
			osm_log(p_vend->p_log, OSM_LOG_ERROR,
				"osm_vendor_send: ERR 3B28: "
				"Unable to create address vector (%s).\n",
				ib_get_err_str(status));

			if (p_vw->p_resp_madw)
				osm_mad_pool_put(p_bind->p_osm_pool,
						 p_vw->p_resp_madw);
			goto Exit;
		}

		if (osm_log_is_active(p_vend->p_log, OSM_LOG_DEBUG)) {
			osm_log(p_vend->p_log, OSM_LOG_DEBUG,
				"osm_vendor_send: "
				"Allocating av handle %p.\n", p_vw->h_av);
		}
	} else {
		p_vw->h_av = p_bind->h_dr_av;
	}

	p_elem->h_av = p_vw->h_av;

	p_elem->context1 = p_madw;
	p_elem->context2 = NULL;

	p_elem->immediate_data = 0;
	p_elem->p_grh = NULL;
	p_elem->resp_expected = resp_expected;
	p_elem->retry_cnt = OSM_DEFAULT_RETRY_COUNT;

	p_elem->send_opt = IB_SEND_OPT_SIGNALED;
	p_elem->timeout_ms = p_vend->timeout;

	/* Completion information. */
	p_elem->status = 0;	/* Not trusting AL */

	if ((p_mad->mgmt_class == IB_MCLASS_SUBN_LID) ||
	    (p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)) {
		p_elem->remote_qp = 0;
		p_elem->remote_qkey = 0;
	} else {
		p_elem->remote_qp = p_mad_addr->addr_type.gsi.remote_qp;
		p_elem->remote_qkey = p_mad_addr->addr_type.gsi.remote_qkey;
		osm_log(p_vend->p_log, OSM_LOG_DEBUG,
			"osm_vendor_send: "
			"remote qp = 0x%X, remote qkey = 0x%X.\n",
			cl_ntoh32(p_elem->remote_qp),
			cl_ntoh32(p_elem->remote_qkey));
	}

	status = ib_send_mad(p_bind->h_svc, p_elem, NULL);
	if (status != IB_SUCCESS) {
		osm_log(p_vend->p_log, OSM_LOG_ERROR,
			"osm_vendor_send: ERR 3B29: "
			"Send failed (%s).\n", ib_get_err_str(status));
		if (p_vw->p_resp_madw)
			osm_mad_pool_put(p_bind->p_osm_pool, p_vw->p_resp_madw);
		goto Exit;
	}

Exit:
	OSM_LOG_EXIT(p_vend->p_log);
	return (status);
}
/**
 * Get the OpenSM bind handle
 */
static int
_get_bind_handle(nodeupdown_t nodeupdown_handle, osm_bind_handle_t *handle)
{
	uint32_t           i = 0;
	uint64_t           port_guid = (uint64_t)-1;
	osm_bind_handle_t  bind_handle;
	ib_api_status_t    status;
	ib_port_attr_t     attr_array[OPENIB_MAX_PORTS];
	uint32_t           num_ports = OPENIB_MAX_PORTS;

	complib_init();

	osm_log_construct(&_openib_log_osm);
	if ((status = osm_log_init( &_openib_log_osm, TRUE,
				    0x0001, NULL, TRUE )) != IB_SUCCESS) {
#ifndef NDEBUG
		fprintf(stderr, "Failed to init osm_log: %s\n",
			ib_get_err_str(status));
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (-1);
	}

#if 0
	osm_log_set_level(&_openib_log_osm, OSM_LOG_DEFAULT_LEVEL);
#else
	osm_log_set_level(&_openib_log_osm, OSM_LOG_NONE);
#endif

        _openib_vendor = osm_vendor_new(&_openib_log_osm, 100);
	osm_mad_pool_construct(&_openib_mad_pool);
#ifdef HAVE_FUNC_OSM_MAD_POOL_INIT_2
	if ((status = osm_mad_pool_init(&_openib_mad_pool, &_openib_log_osm)) != IB_SUCCESS) {
#else
	if ((status = osm_mad_pool_init(&_openib_mad_pool)) != IB_SUCCESS) {
#endif
#ifndef NDEBUG
		fprintf(stderr, "Failed to init mad pool: %s\n",
			ib_get_err_str(status));
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (-1);
	}

	if ((status = osm_vendor_get_all_port_attr(_openib_vendor, attr_array, &num_ports)) != IB_SUCCESS) {
#ifndef NDEBUG
		fprintf(stderr, "Failed to get port attributes: %s\n",
			ib_get_err_str(status));
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (-1);
	}

	for (i = 0; i < num_ports; i++) {
		if (attr_array[i].link_state == IB_LINK_ACTIVE)
			port_guid = attr_array[i].port_guid;
	}

	if (port_guid == (uint64_t)-1) {
#ifndef NDEBUG
		fprintf(stderr, "Failed to find active port, check port status with \"ibstat\"\n");
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (-1);
	}

	bind_handle = osmv_bind_sa(_openib_vendor, &_openib_mad_pool, port_guid);

	if (bind_handle == OSM_BIND_INVALID_HANDLE) {
#ifndef NDEBUG
		fprintf(stderr, "Failed to bind to SA\n");
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return(-1);
	}
	*handle = bind_handle;
	return (0);
}

/**
 * Get all the records available for requested query type.
 */
static ib_api_status_t
_get_all_records(nodeupdown_t nodeupdown_handle,
		 osm_bind_handle_t bind_handle,
		 ib_net16_t query_id,
		 ib_net16_t attr_offset,
		 int trusted)
{
	ib_api_status_t   status;
	osmv_query_req_t  req;
	osmv_user_query_t user;

	memset( &req, 0, sizeof( req ) );
	memset( &user, 0, sizeof( user ) );

	user.attr_id = query_id;
	user.attr_offset = attr_offset;

	req.query_type = OSMV_QUERY_USER_DEFINED;
	req.timeout_ms = 100;
	req.retry_cnt = 1;
	req.flags = OSM_SA_FLAGS_SYNC;
	req.query_context = NULL;
	req.pfn_query_cb = _query_res_cb;
	req.p_query_input = &user;
	if (trusted)
		req.sm_key = OSM_DEFAULT_SM_KEY;
	else
		req.sm_key = 0;

	if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {
#ifndef NDEBUG
		fprintf(stderr, "Query SA failed: %s\n",
			ib_get_err_str(status));
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (status);
	}

	if (_openib_result.status != IB_SUCCESS) {
#ifndef NDEBUG
		fprintf(stderr, "Query _openib_result returned: %s\n",
			ib_get_err_str(_openib_result.status));
#endif /* NDEBUG */
		nodeupdown_set_errnum(nodeupdown_handle, NODEUPDOWN_ERR_BACKEND_MODULE);
		return (_openib_result.status);
	}
	return (status);
}
Exemple #30
0
osm_bind_handle_t
osmv_bind_sa(IN osm_vendor_t * const p_vend,
	     IN osm_mad_pool_t * const p_mad_pool, IN ib_net64_t port_guid)
{
	osm_bind_info_t bind_info;
	osm_log_t *p_log = p_vend->p_log;
	ib_api_status_t status = IB_SUCCESS;
	osmv_sa_bind_info_t *p_sa_bind_info;
	cl_status_t cl_status;

	OSM_LOG_ENTER(p_log);

	osm_log(p_log, OSM_LOG_DEBUG,
		"osmv_bind_sa: "
		"Binding to port 0x%" PRIx64 ".\n", cl_ntoh64(port_guid));

	bind_info.port_guid = port_guid;
	bind_info.mad_class = IB_MCLASS_SUBN_ADM;
	bind_info.class_version = 2;
	bind_info.is_responder = TRUE;
	bind_info.is_trap_processor = FALSE;
	bind_info.is_report_processor = TRUE;
	bind_info.send_q_size = 256;
	bind_info.recv_q_size = 256;

	/* allocate the new sa bind info */
	p_sa_bind_info =
	    (osmv_sa_bind_info_t *) malloc(sizeof(osmv_sa_bind_info_t));
	if (!p_sa_bind_info) {
		osm_log(p_log, OSM_LOG_ERROR,
			"osmv_bind_sa: ERR 0505: "
			"Fail to allocate new bidn structure\n");
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
		goto Exit;
	}

	/* store some important context */
	p_sa_bind_info->p_log = p_log;
	p_sa_bind_info->port_guid = port_guid;
	p_sa_bind_info->p_mad_pool = p_mad_pool;
	p_sa_bind_info->p_vendor = p_vend;
	p_sa_bind_info->last_lids_update_sec = 0;

	/* Bind to the lower level */
	p_sa_bind_info->h_bind = osm_vendor_bind(p_vend, &bind_info, p_mad_pool, __osmv_sa_mad_rcv_cb, __osmv_sa_mad_err_cb, p_sa_bind_info);	/* context provided to CBs */

	if (p_sa_bind_info->h_bind == OSM_BIND_INVALID_HANDLE) {
		free(p_sa_bind_info);
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
		osm_log(p_log, OSM_LOG_ERROR,
			"osmv_bind_sa: ERR 0506: "
			"Fail to bind to vendor SMI.\n");
		goto Exit;
	}

	/* obtain the sm_lid from the vendor */
	status =
	    __osmv_get_lid_and_sm_lid_by_port_guid(p_vend, port_guid,
						   &p_sa_bind_info->
						   last_lids_update_sec,
						   &p_sa_bind_info->lid,
						   &p_sa_bind_info->sm_lid);
	if (status != IB_SUCCESS) {
		free(p_sa_bind_info);
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
		osm_log(p_log, OSM_LOG_ERROR,
			"osmv_bind_sa: ERR 0507: "
			"Fail to obtain the sm lid.\n");
		goto Exit;
	}

	/* initialize the sync_event */
	cl_event_construct(&p_sa_bind_info->sync_event);
	cl_status = cl_event_init(&p_sa_bind_info->sync_event, TRUE);
	if (cl_status != CL_SUCCESS) {
		osm_log(p_log, OSM_LOG_ERROR,
			"osmv_bind_sa: ERR 0508: "
			"cl_init_event failed: %s\n", ib_get_err_str(cl_status)
		    );
		free(p_sa_bind_info);
		p_sa_bind_info = OSM_BIND_INVALID_HANDLE;
	}

Exit:
	OSM_LOG_EXIT(p_log);
	return (p_sa_bind_info);
}