Example #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);
}
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);
}
Example #3
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);
	}
}