Пример #1
0
/* 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;
}
Пример #2
0
/*
  Call back on new mad received:

  We basically only need to set the context of the query.
  Or report an error.

  A pointer to the actual context of the request (a copy of the oriignal
  request structure) is attached as the p_madw->context.ni_context.node_guid
*/
static void
__osmv_sa_mad_rcv_cb(IN osm_madw_t * p_madw,
		     IN void *bind_context, IN osm_madw_t * p_req_madw)
{
	osmv_sa_bind_info_t *p_bind = (osmv_sa_bind_info_t *) bind_context;
	osmv_query_req_t *p_query_req_copy = NULL;
	osmv_query_res_t query_res;
	ib_sa_mad_t *p_sa_mad;
	ib_net16_t mad_status;

	OSM_LOG_ENTER(p_bind->p_log);

	if (!p_req_madw) {
		OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
			"Ignoring a non-response mad\n");
		osm_mad_pool_put(p_bind->p_mad_pool, p_madw);
		goto Exit;
	}

	/* obtain the sent context since we store it during send in the ni_ctx */
	p_query_req_copy =
	    (osmv_query_req_t *) (long *)(long)(p_req_madw->context.ni_context.
						node_guid);

	/* provide the context of the original request in the result */
	query_res.query_context = p_query_req_copy->query_context;

	/* provide the resulting madw */
	query_res.p_result_madw = p_madw;

	/* update the req fields */
	p_sa_mad = (ib_sa_mad_t *) p_madw->p_mad;

	/* if we got a remote error track it in the status */
	mad_status = (ib_net16_t) (p_sa_mad->status & IB_SMP_STATUS_MASK);
	if (mad_status != IB_SUCCESS) {
		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5501: "
			"Remote error:0x%04X\n", cl_ntoh16(mad_status));
		query_res.status = IB_REMOTE_ERROR;
	} else
		query_res.status = IB_SUCCESS;

	/* what if we have got back an empty mad ? */
	if (!p_madw->mad_size) {
		OSM_LOG(p_bind->p_log, OSM_LOG_ERROR, "ERR 5502: "
			"Got an empty mad\n");
		query_res.status = IB_ERROR;
	}

	if (IB_SUCCESS == mad_status) {

		/* if we are in not in a method response of an rmpp nature we must get only 1 */
		/* HACK: in the future we might need to be smarter for other methods... */
		if (p_sa_mad->method != IB_MAD_METHOD_GETTABLE_RESP) {
			query_res.result_cnt = 1;
		} else {
#ifndef VENDOR_RMPP_SUPPORT
			if (mad_status != IB_SUCCESS)
				query_res.result_cnt = 0;
			else
				query_res.result_cnt = 1;
#else
			if (ib_get_attr_size(p_sa_mad->attr_offset)) {
				/* we used the offset value to calculate the
				   number of records in here */
				query_res.result_cnt = (uintn_t)
				    ((p_madw->mad_size - IB_SA_MAD_HDR_SIZE) /
				     ib_get_attr_size(p_sa_mad->attr_offset));
				OSM_LOG(p_bind->p_log, OSM_LOG_DEBUG,
					"Count = %u = %zu / %u (%zu)\n",
					query_res.result_cnt,
					p_madw->mad_size - IB_SA_MAD_HDR_SIZE,
					ib_get_attr_size(p_sa_mad->attr_offset),
					(p_madw->mad_size -
					 IB_SA_MAD_HDR_SIZE) %
					ib_get_attr_size(p_sa_mad->attr_offset));
			} else
				query_res.result_cnt = 0;
#endif
		}
	}

	query_res.query_type = p_query_req_copy->query_type;

	p_query_req_copy->pfn_query_cb(&query_res);

	if ((p_query_req_copy->flags & OSM_SA_FLAGS_SYNC) == OSM_SA_FLAGS_SYNC)
		cl_event_signal(&p_bind->sync_event);

Exit:

	/* free the copied query request if found */
	if (p_query_req_copy)
		free(p_query_req_copy);

	/* put back the request madw */
	if (p_req_madw)
		osm_mad_pool_put(p_bind->p_mad_pool, p_req_madw);

	OSM_LOG_EXIT(p_bind->p_log);
}
Пример #3
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;
}