Exemple #1
0
void osm_sa_send_error(IN osm_sa_t * sa, IN const osm_madw_t * p_madw,
		       IN ib_net16_t sa_status)
{
	osm_madw_t *p_resp_madw;
	ib_sa_mad_t *p_resp_sa_mad;
	ib_sa_mad_t *p_sa_mad;

	OSM_LOG_ENTER(sa->p_log);

	/* avoid races - if we are exiting - exit */
	if (osm_exit_flag) {
		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"Ignoring requested send after exit\n");
		goto Exit;
	}

	p_resp_madw = osm_mad_pool_get(sa->p_mad_pool,
				       p_madw->h_bind, MAD_BLOCK_SIZE,
				       &p_madw->mad_addr);

	if (p_resp_madw == NULL) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: "
			"Unable to acquire response MAD\n");
		goto Exit;
	}

	p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);
	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);

	/*  Copy the MAD header back into the response mad */
	*p_resp_sa_mad = *p_sa_mad;
	p_resp_sa_mad->status = sa_status;

	if (p_resp_sa_mad->method == IB_MAD_METHOD_SET)
		p_resp_sa_mad->method = IB_MAD_METHOD_GET;
	else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE)
		p_resp_sa_mad->attr_offset = 0;

	p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;

	/*
	 * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884)
	 */
	p_resp_sa_mad->sm_key = 0;

	/*
	 * o15-0.2.7 - The PathRecord Attribute ID shall be used in
	 * the response (to a SubnAdmGetMulti(MultiPathRecord)
	 */
	if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD)
		p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD;

	if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES))
		osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES);

	osm_sa_send(sa, p_resp_madw, FALSE);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
Exemple #2
0
ib_api_status_t
osm_resp_send(IN osm_sm_t * sm,
	      IN const osm_madw_t * const p_req_madw,
	      IN const ib_net16_t mad_status,
	      IN const uint8_t * const p_payload)
{
	const ib_smp_t *p_req_smp;
	ib_smp_t *p_smp;
	osm_madw_t *p_madw;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_req_madw);
	CL_ASSERT(p_payload);

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

	p_madw = osm_mad_pool_get(sm->p_mad_pool,
				  osm_madw_get_bind_handle(p_req_madw),
				  MAD_BLOCK_SIZE, NULL);

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

	/*
	   Copy the request smp to the response smp, then just
	   update the necessary fields.
	 */
	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_req_smp = osm_madw_get_smp_ptr(p_req_madw);
	osm_resp_make_resp_smp(sm, p_req_smp, mad_status, p_payload, p_smp);
	p_madw->mad_addr.dest_lid =
	    p_req_madw->mad_addr.addr_type.smi.source_lid;
	p_madw->mad_addr.addr_type.smi.source_lid =
	    p_req_madw->mad_addr.dest_lid;

	p_madw->resp_expected = FALSE;
	p_madw->fail_msg = CL_DISP_MSGID_NONE;

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Responding to %s (0x%X)"
		"\n\t\t\t\tattribute modifier 0x%X, TID 0x%" PRIx64 "\n",
		ib_get_sm_attr_str(p_smp->attr_id), cl_ntoh16(p_smp->attr_id),
		cl_ntoh32(p_smp->attr_mod), cl_ntoh64(p_smp->trans_id));

	osm_vl15_post(sm->p_vl15, p_madw);

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return (status);
}
static void
__osmv_dispatch_simple_mad(IN osm_bind_handle_t h_bind,
			   IN const ib_mad_t * p_mad,
			   IN osmv_txn_ctx_t * p_txn,
			   IN const osm_mad_addr_t * p_mad_addr)
{
	osm_madw_t *p_madw;
	ib_mad_t *p_mad_buf;
	osm_madw_t *p_req_madw = NULL;
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	/* Build the MAD wrapper to be returned to the user.
	 * The actual storage for the MAD is allocated there.
	 */
	p_madw =
	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, MAD_BLOCK_SIZE,
			     p_mad_addr);

	if (NULL == p_madw) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_simple_mad: ERR 6501: "
			"Out Of Memory - could not allocate a buffer of size %d\n",
			MAD_BLOCK_SIZE);

		goto dispatch_simple_mad_done;
	}

	p_mad_buf = osm_madw_get_mad_ptr(p_madw);
	/* Copy the payload to the MAD buffer */
	memcpy((void *)p_mad_buf, (void *)p_mad, MAD_BLOCK_SIZE);

	if (NULL != p_txn) {
		/* This is a RESPONSE MAD. Pair it with the REQUEST MAD, pass upstream */
		p_req_madw = p_txn->p_madw;
		CL_ASSERT(NULL != p_req_madw);

		p_mad_buf->trans_id = cl_hton64(osmv_txn_get_tid(p_txn));
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Restoring the original TID to 0x%" PRIx64 "\n",
			cl_ntoh64(p_mad_buf->trans_id));

		/* Reply matched, transaction complete */
		osmv_txn_done(h_bind, osmv_txn_get_key(p_txn), FALSE);
	} else {
		/* This is a REQUEST  MAD. Don't create a context, pass upstream */
	}

	/* Do the job ! */
	p_bo->recv_cb(p_madw, p_bo->cb_context, p_req_madw);

dispatch_simple_mad_done:
	OSM_LOG_EXIT(p_bo->p_vendor->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;
}
/**********************************************************************
 * TS RCV Thread callback
 * HACK: - we need to make this support arbitrary size mads.
 **********************************************************************/
void
__osm_ts_rcv_callback(IN osm_ts_bind_info_t * p_bind,
		      IN osm_mad_addr_t * p_mad_addr,
		      IN uint32_t mad_size, IN void *p_mad)
{
	ib_api_status_t status;
	osm_madw_t *p_req_madw = NULL;
	osm_madw_t *p_madw;
	osm_vend_wrap_t *p_new_vw;
	ib_mad_t *p_mad_buf;
	osm_log_t *const p_log = p_bind->p_vend->p_log;

	OSM_LOG_ENTER(p_log);

	/* if it is a response MAD we mustbe able to get the request */
	if (ib_mad_is_response((ib_mad_t *) p_mad)) {
		/* can we find a matching madw by this payload TID */
		status =
		    osm_transaction_mgr_get_madw_for_tid(p_bind->p_vend,
							 (ib_mad_t *) p_mad,
							 &p_req_madw);
		if (status != IB_SUCCESS) {
			osm_log(p_log, OSM_LOG_ERROR,
				"__osm_ts_rcv_callback: ERR 5008: "
				"Error obtaining request madw by TID (%d).\n",
				status);
			p_req_madw = NULL;
		}

		if (p_req_madw == NULL) {
			osm_log(p_log, OSM_LOG_ERROR,
				"__osm_ts_rcv_callback: ERR 5009:  "
				"Fail to obtain request madw for receined MAD. Aborting CB.\n");
			goto Exit;
		}
	}

	/* do we have a request ??? */
	if (p_req_madw == NULL) {

		/* if not - get new osm_madw and arrange it. */
		/* create the new madw in the pool */
		p_madw = osm_mad_pool_get(p_bind->p_osm_pool,
					  (osm_bind_handle_t) p_bind,
					  mad_size, p_mad_addr);
		if (p_madw == NULL) {
			osm_log(p_log, OSM_LOG_ERROR,
				"__osm_ts_rcv_callback: ERR 5010: "
				"Error request for a new madw.\n");
			goto Exit;
		}
		/* HACK: we cust to avoid the const ??? */
		p_mad_buf = (void *)p_madw->p_mad;
	} else {
		/* we have the madw defined during the send and stored in the vend_wrap */
		/* we need to make sure the wrapper is correctly init there */
		CL_ASSERT(p_req_madw->vend_wrap.p_resp_madw != 0);
		p_madw = p_req_madw->vend_wrap.p_resp_madw;

		CL_ASSERT(p_madw->h_bind);
		p_mad_buf =
		    osm_vendor_get(p_madw->h_bind, mad_size,
				   &p_madw->vend_wrap);

		if (p_mad_buf == NULL) {
			osm_log(p_log, OSM_LOG_ERROR,
				"__osm_ts_rcv_callback: ERR 5011: "
				"Unable to acquire wire MAD.\n");

			goto Exit;
		}

		/*
		   Finally, attach the wire MAD to this wrapper.
		 */
		osm_madw_set_mad(p_madw, p_mad_buf);
	}

	/* init some fields of the vendor wrapper */
	p_new_vw = osm_madw_get_vend_ptr(p_madw);
	p_new_vw->h_bind = p_bind;
	p_new_vw->size = mad_size;
	p_new_vw->p_resp_madw = NULL;
	p_new_vw->p_mad_buf = p_mad_buf;

	memcpy(p_new_vw->p_mad_buf, p_mad, mad_size);

	/* attach the buffer to the wrapper */
	p_madw->p_mad = p_mad_buf;

	/* we can also make sure we marked the size and bind on the returned madw */
	p_madw->h_bind = p_new_vw->h_bind;

	/* call the CB */
	(*(osm_vend_mad_recv_callback_t) p_bind->rcv_callback)
	    (p_madw, p_bind->client_context, p_req_madw);

Exit:
	OSM_LOG_EXIT(p_log);
}
Exemple #6
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;
}
static void cpi_rcv_respond(IN osm_sa_t * sa, IN const osm_madw_t * p_madw)
{
	osm_madw_t *p_resp_madw;
	const ib_sa_mad_t *p_sa_mad;
	ib_sa_mad_t *p_resp_sa_mad;
	ib_class_port_info_t *p_resp_cpi;
	ib_gid_t zero_gid;
	uint32_t cap_mask2;
	uint8_t rtv;

	OSM_LOG_ENTER(sa->p_log);

	memset(&zero_gid, 0, sizeof(ib_gid_t));

	/*
	   Get a MAD to reply. Address of Mad is in the received mad_wrapper
	 */
	p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, p_madw->h_bind,
				       MAD_BLOCK_SIZE, &p_madw->mad_addr);
	if (!p_resp_madw) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 1408: "
			"Unable to allocate MAD\n");
		goto Exit;
	}

	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
	p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw);

	memcpy(p_resp_sa_mad, p_sa_mad, IB_SA_MAD_HDR_SIZE);
	p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
	/* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
	p_resp_sa_mad->sm_key = 0;

	p_resp_cpi =
	    (ib_class_port_info_t *) ib_sa_mad_get_payload_ptr(p_resp_sa_mad);

	/* finally do it (the job) man ! */
	p_resp_cpi->base_ver = 1;
	p_resp_cpi->class_ver = 2;
	/* Calculate encoded response time value */
	/* transaction timeout is in msec */
	if (sa->p_subn->opt.transaction_timeout >
	    msecs_to_rtv_table[MAX_MSECS_TO_RTV - 1])
		rtv = MAX_MSECS_TO_RTV - 1;
	else {
		for (rtv = 0; rtv < MAX_MSECS_TO_RTV; rtv++) {
			if (sa->p_subn->opt.transaction_timeout <=
			    msecs_to_rtv_table[rtv])
				break;
		}
	}
	rtv += 8;
	ib_class_set_resp_time_val(p_resp_cpi, rtv);
	p_resp_cpi->redir_gid = zero_gid;
	p_resp_cpi->redir_tc_sl_fl = 0;
	p_resp_cpi->redir_lid = 0;
	p_resp_cpi->redir_pkey = 0;
	p_resp_cpi->redir_qp = CL_NTOH32(1);
	p_resp_cpi->redir_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
	p_resp_cpi->trap_gid = zero_gid;
	p_resp_cpi->trap_tc_sl_fl = 0;
	p_resp_cpi->trap_lid = 0;
	p_resp_cpi->trap_pkey = 0;
	p_resp_cpi->trap_hop_qp = 0;
	p_resp_cpi->trap_qkey = IB_QP1_WELL_KNOWN_Q_KEY;

	/* set specific capability mask bits */
	/* we do not support the following options/optional records:
	   OSM_CAP_IS_SUBN_OPT_RECS_SUP :
	   RandomForwardingTableRecord,
	   ServiceAssociationRecord
	   other optional records supported "under the table"

	   OSM_CAP_IS_MULTIPATH_SUP:
	   TraceRecord

	   OSM_CAP_IS_REINIT_SUP:
	   For reinitialization functionality.

	   So not sending traps, but supporting Get(Notice) and Set(Notice).
	 */

	/* Note host notation replaced later */
#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP)
	p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
	    OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED |
	    OSM_CAP_IS_MULTIPATH_SUP;
#else
	p_resp_cpi->cap_mask = OSM_CAP_IS_SUBN_GET_SET_NOTICE_SUP |
	    OSM_CAP_IS_PORT_INFO_CAPMASK_MATCH_SUPPORTED;
#endif
	cap_mask2 = OSM_CAP2_IS_FULL_PORTINFO_REC_SUPPORTED |
		    OSM_CAP2_IS_EXTENDED_SPEEDS_SUPPORTED |
		    OSM_CAP2_IS_ALIAS_GUIDS_SUPPORTED |
		    OSM_CAP2_IS_MULTICAST_SERVICE_RECS_SUPPORTED |
		    OSM_CAP2_IS_PORT_INFO_CAPMASK2_MATCH_SUPPORTED |
		    OSM_CAP2_IS_LINK_WIDTH_2X_SUPPORTED;
	if (sa->p_subn->opt.use_mfttop)
		cap_mask2 |= OSM_CAP2_IS_MCAST_TOP_SUPPORTED;
	if (sa->p_subn->opt.qos)
		cap_mask2 |= OSM_CAP2_IS_QOS_SUPPORTED;
	ib_class_set_cap_mask2(p_resp_cpi, cap_mask2);

	if (!sa->p_subn->opt.disable_multicast)
		p_resp_cpi->cap_mask |= OSM_CAP_IS_UD_MCAST_SUP;
	p_resp_cpi->cap_mask = cl_hton16(p_resp_cpi->cap_mask);

	if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_FRAMES))
		osm_dump_sa_mad_v2(sa->p_log, p_resp_sa_mad, FILE_ID, OSM_LOG_FRAMES);

	osm_sa_send(sa, p_resp_madw, FALSE);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
Exemple #8
0
void osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size,
		    cl_qlist_t *list)
{
	struct item_data {
		cl_list_item_t list;
		char data[0];
	};
	cl_list_item_t *item;
	osm_madw_t *resp_madw;
	ib_sa_mad_t *sa_mad, *resp_sa_mad;
	unsigned num_rec, i;
#ifndef VENDOR_RMPP_SUPPORT
	unsigned trim_num_rec;
#endif
	unsigned char *p;

	sa_mad = osm_madw_get_sa_mad_ptr(madw);
	num_rec = cl_qlist_count(list);

	/*
	 * C15-0.1.30:
	 * If we do a SubnAdmGet and got more than one record it is an error!
	 */
	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: "
			"Got %u records for SubnAdmGet(%s) comp_mask 0x%016" PRIx64 "\n",
			num_rec, ib_get_sa_attr_str(sa_mad->attr_id),
			cl_ntoh64(sa_mad->comp_mask));
		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS);
		goto Exit;
	}

#ifndef VENDOR_RMPP_SUPPORT
	trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size;
	if (trim_num_rec < num_rec) {
		OSM_LOG(sa->p_log, OSM_LOG_VERBOSE,
			"Number of records:%u trimmed to:%u to fit in one MAD\n",
			num_rec, trim_num_rec);
		num_rec = trim_num_rec;
	}
#endif

	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec);

	if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) {
		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS);
		goto Exit;
	}

	/*
	 * Get a MAD to reply. Address of Mad is in the received mad_wrapper
	 */
	resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind,
				     num_rec * attr_size + IB_SA_MAD_HDR_SIZE,
				     &madw->mad_addr);
	if (!resp_madw) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: "
			"osm_mad_pool_get failed\n");
		osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES);
		goto Exit;
	}

	resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw);

	/*
	   Copy the MAD header back into the response mad.
	   Set the 'R' bit and the payload length,
	   Then copy all records from the list into the response payload.
	 */

	memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE);
	if (resp_sa_mad->method == IB_MAD_METHOD_SET)
		resp_sa_mad->method = IB_MAD_METHOD_GET;
	resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK;
	/* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */
	resp_sa_mad->sm_key = 0;

	/* Fill in the offset (paylen will be done by the rmpp SAR) */
	resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0;

	p = ib_sa_mad_get_payload_ptr(resp_sa_mad);

#ifndef VENDOR_RMPP_SUPPORT
	/* we support only one packet RMPP - so we will set the first and
	   last flags for gettable */
	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) {
		resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA;
		resp_sa_mad->rmpp_flags =
		    IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST |
		    IB_RMPP_FLAG_ACTIVE;
	}
#else
	/* forcefully define the packet as RMPP one */
	if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP)
		resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE;
#endif

	for (i = 0; i < num_rec; i++) {
		item = cl_qlist_remove_head(list);
		memcpy(p, ((struct item_data *)item)->data, attr_size);
		p += attr_size;
		free(item);
	}

	osm_dump_sa_mad(sa->p_log, resp_sa_mad, OSM_LOG_FRAMES);
	osm_sa_send(sa, resp_madw, FALSE);

Exit:
	/* need to set the mem free ... */
	item = cl_qlist_remove_head(list);
	while (item != cl_qlist_end(list)) {
		free(item);
		item = cl_qlist_remove_head(list);
	}
}
static ib_api_status_t
__osmv_dispatch_rmpp_rcv(IN osm_bind_handle_t h_bind,
			 IN const ib_mad_t * p_mad,
			 IN osmv_txn_ctx_t * p_txn,
			 IN const osm_mad_addr_t * p_mad_addr)
{
	ib_api_status_t status = IB_SUCCESS;
	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;
	boolean_t is_last1 = FALSE, is_last2 = FALSE;
	osm_madw_t *p_new_madw = NULL, *p_req_madw = NULL;
	ib_mad_t *p_mad_buf;
	uint32_t size = 0;
	uint64_t key = osmv_txn_get_key(p_txn);
	uint64_t tid = osmv_txn_get_tid(p_txn);

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	if (TRUE == osmv_rmpp_is_ack(p_mad)) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Not supposed to receive ACK's --> dropping the MAD\n");

		goto dispatch_rmpp_rcv_done;
	}

	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"__osmv_dispatch_rmpp_rcv: ERR 6504: "
			"The Remote Side stopped sending\n");

		status = IB_REMOTE_ERROR;
		goto dispatch_rmpp_rcv_done;
	}

	status = __osmv_dispatch_accept_seg(h_bind, p_txn, p_mad);
	switch (status) {

	case IB_SUCCESS:

		/* Check wheter this is the legal last MAD */
		/* Criteria #1: the received MAD is marked last */
		is_last1 = osmv_rmpp_is_last(p_mad);

		/* Criteria #2: the total accumulated length hits the advertised one */
		is_last2 = is_last1;

		size = osmv_rmpp_recv_ctx_get_byte_num_from_first(p_recv_ctx);
		if (size > 0) {
			is_last2 =
			    (osmv_rmpp_recv_ctx_get_cur_byte_num(p_recv_ctx) >=
			     size);
		}

		if (is_last1 != is_last2) {

			osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
					   IB_RMPP_TYPE_ABORT,
					   IB_RMPP_STATUS_BAD_LEN);

			status = IB_ERROR;
			goto dispatch_rmpp_rcv_done;
		}

		/* TBD Consider an optimization - sending an ACK
		 * only for the last segment in the window
		 */
		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
		break;

	case IB_INSUFFICIENT_RESOURCES:
		/* An out-of-order segment received. Send the ACK anyway */
		__osmv_dispatch_send_ack(h_bind, p_mad, p_txn, p_mad_addr);
		status = IB_SUCCESS;
		goto dispatch_rmpp_rcv_done;

	case IB_INSUFFICIENT_MEMORY:
		osmv_rmpp_send_nak(h_bind, p_mad, p_mad_addr,
				   IB_RMPP_TYPE_STOP, IB_RMPP_STATUS_RESX);
		goto dispatch_rmpp_rcv_done;

	default:
		/* Illegal return code */
		CL_ASSERT(FALSE);
	}

	if (TRUE != is_last1) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"RMPP MADW assembly continues, TID=0x%" PRIx64 "\n", tid);
		goto dispatch_rmpp_rcv_done;
	}

	/* This is the last packet. */
	if (0 == size) {
		/* The total size was not advertised in the first packet */
		size = osmv_rmpp_recv_ctx_get_byte_num_from_last(p_recv_ctx);
	}

	/*
	   NOTE: the received mad might not be >= 256 bytes.
	   some MADs might contain several SA records but still be
	   less then a full MAD.
	   We have to use RMPP to send them over since on a regular
	   "simple" MAD there is no way to know how many records were sent
	 */

	/* Build the MAD wrapper to be returned to the user.
	 * The actual storage for the MAD is allocated there.
	 */
	p_new_madw =
	    osm_mad_pool_get(p_bo->p_osm_pool, h_bind, size, p_mad_addr);
	if (NULL == p_new_madw) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_rcv: ERR 6506: "
			"Out Of Memory - could not allocate %d bytes for the MADW\n",
			size);

		status = IB_INSUFFICIENT_MEMORY;
		goto dispatch_rmpp_rcv_done;
	}

	p_req_madw = osmv_txn_get_madw(p_txn);
	p_mad_buf = osm_madw_get_mad_ptr(p_new_madw);
	status = osmv_rmpp_recv_ctx_reassemble_arbt_mad(p_recv_ctx, size,
							(uint8_t *) p_mad_buf);
	if (IB_SUCCESS != status) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_rcv: ERR 6507: "
			"Internal error - could not reassemble the result MAD\n");
		goto dispatch_rmpp_rcv_done;	/* What can happen here? */
	}

	/* The MAD is assembled, we are about to apply the callback.
	 * Delete the transaction context, unless the transaction is double sided */
	if (FALSE == osmv_txn_is_rmpp_init_by_peer(p_txn)
	    || FALSE == osmv_mad_is_multi_resp(p_mad)) {

		osmv_txn_done(h_bind, key, FALSE);
	}

	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"RMPP MADW %p assembly complete, TID=0x%" PRIx64 "\n", p_new_madw,
		tid);

	p_mad_buf->trans_id = cl_hton64(tid);
	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"Restoring the original TID to 0x%" PRIx64 "\n",
		cl_ntoh64(p_mad_buf->trans_id));

	/* Finally, do the job! */
	p_bo->recv_cb(p_new_madw, p_bo->cb_context, p_req_madw);

dispatch_rmpp_rcv_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return status;
}
Exemple #10
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;
}
Exemple #11
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;
}