コード例 #1
0
ファイル: ibConnection.cpp プロジェクト: 4Second2None/Collage
bool IBConnection::_readKeys( struct IBDest *remDest)
{
    int parsed;
    eq::lunchbox::Buffer<void*> buf;
    buf.resize( KEY_MSG_SIZE );
    uint64_t size = KEY_MSG_SIZE;
    WSABUF wsaBuffer = { KEY_MSG_SIZE,
                         reinterpret_cast< char* >( buf.getData() ) };
    DWORD  got   = 0;
    DWORD  flags = 0;

    _socketConnection->readNB( wsaBuffer.buf, size);
    _socketConnection->readSync( wsaBuffer.buf, size);

    char* data = reinterpret_cast<char*>(buf.getData());

    parsed = sscanf( data,
                     KEY_PRINT_FMT,
                     &remDest->lid,
                     &remDest->qpn,
                     &remDest->psn,
                     &remDest->rkey,
                     &remDest->vaddr );

    remDest->lid  = cl_ntoh16(remDest->lid);
    remDest->qpn  = cl_ntoh32(remDest->qpn);
    remDest->psn  = cl_ntoh32(remDest->psn);
    remDest->rkey = cl_ntoh32(remDest->rkey);

    if ( parsed != 5 )
        return false;

    remDest->vaddr = ( uintptr_t ) remDest->vaddr;
    return true;
}
コード例 #2
0
ファイル: osm_sa.c プロジェクト: Cai900205/test
static void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt)
{
	struct opensm_dump_context dump_context;
	osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm;
	FILE *file = ((struct opensm_dump_context *)cxt)->file;

	fprintf(file, "MC Group 0x%04x %s:"
		" mgid=0x%016" PRIx64 ":0x%016" PRIx64
		" port_gid=0x%016" PRIx64 ":0x%016" PRIx64
		" qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x"
		" pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x"
		" scope_state=0x%02x proxy_join=0x%x" "\n\n",
		cl_ntoh16(p_mgrp->mlid),
		p_mgrp->well_known ? " (well known)" : "",
		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix),
		cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id),
		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix),
		cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id),
		cl_ntoh32(p_mgrp->mcmember_rec.qkey),
		cl_ntoh16(p_mgrp->mcmember_rec.mlid),
		p_mgrp->mcmember_rec.mtu,
		p_mgrp->mcmember_rec.tclass,
		cl_ntoh16(p_mgrp->mcmember_rec.pkey),
		p_mgrp->mcmember_rec.rate,
		p_mgrp->mcmember_rec.pkt_life,
		cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop),
		p_mgrp->mcmember_rec.scope_state,
		p_mgrp->mcmember_rec.proxy_join);

	dump_context.p_osm = p_osm;
	dump_context.file = file;

	cl_qmap_apply_func(&p_mgrp->mcm_port_tbl,
			   mcast_mgr_dump_one_port, &dump_context);
}
コード例 #3
0
ファイル: osm_sa.c プロジェクト: Cai900205/test
static void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt)
{
	FILE *file = ((struct opensm_dump_context *)cxt)->file;
	osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item;
	ib_service_record_t *p_sr = &p_svcr->service_record;

	fprintf(file, "Service Record: id=0x%016" PRIx64
		" gid=0x%016" PRIx64 ":0x%016" PRIx64
		" pkey=0x%x"
		" lease=0x%x"
		" key=0x%02x%02x%02x%02x%02x%02x%02x%02x"
		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
		" name=\'%s\'"
		" data8=0x%02x%02x%02x%02x%02x%02x%02x%02x"
		":0x%02x%02x%02x%02x%02x%02x%02x%02x"
		" data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x"
		" data32=0x%08x%08x:0x%08x%08x"
		" data64=0x%016" PRIx64 ":0x%016" PRIx64
		" modified_time=0x%x lease_period=0x%x\n\n",
		cl_ntoh64(p_sr->service_id),
		cl_ntoh64(p_sr->service_gid.unicast.prefix),
		cl_ntoh64(p_sr->service_gid.unicast.interface_id),
		cl_ntoh16(p_sr->service_pkey),
		cl_ntoh32(p_sr->service_lease),
		p_sr->service_key[0], p_sr->service_key[1],
		p_sr->service_key[2], p_sr->service_key[3],
		p_sr->service_key[4], p_sr->service_key[5],
		p_sr->service_key[6], p_sr->service_key[7],
		p_sr->service_key[8], p_sr->service_key[9],
		p_sr->service_key[10], p_sr->service_key[11],
		p_sr->service_key[12], p_sr->service_key[13],
		p_sr->service_key[14], p_sr->service_key[15],
		p_sr->service_name,
		p_sr->service_data8[0], p_sr->service_data8[1],
		p_sr->service_data8[2], p_sr->service_data8[3],
		p_sr->service_data8[4], p_sr->service_data8[5],
		p_sr->service_data8[6], p_sr->service_data8[7],
		p_sr->service_data8[8], p_sr->service_data8[9],
		p_sr->service_data8[10], p_sr->service_data8[11],
		p_sr->service_data8[12], p_sr->service_data8[13],
		p_sr->service_data8[14], p_sr->service_data8[15],
		cl_ntoh16(p_sr->service_data16[0]),
		cl_ntoh16(p_sr->service_data16[1]),
		cl_ntoh16(p_sr->service_data16[2]),
		cl_ntoh16(p_sr->service_data16[3]),
		cl_ntoh16(p_sr->service_data16[4]),
		cl_ntoh16(p_sr->service_data16[5]),
		cl_ntoh16(p_sr->service_data16[6]),
		cl_ntoh16(p_sr->service_data16[7]),
		cl_ntoh32(p_sr->service_data32[0]),
		cl_ntoh32(p_sr->service_data32[1]),
		cl_ntoh32(p_sr->service_data32[2]),
		cl_ntoh32(p_sr->service_data32[3]),
		cl_ntoh64(p_sr->service_data64[0]),
		cl_ntoh64(p_sr->service_data64[1]),
		p_svcr->modified_time, p_svcr->lease_period);
}
コード例 #4
0
void
perfmgr_db_fill_data_cnt_read_pc(ib_port_counters_t * wire_read,
				 perfmgr_db_data_cnt_reading_t * reading)
{
	reading->xmit_data = cl_ntoh32(wire_read->xmit_data);
	reading->rcv_data = cl_ntoh32(wire_read->rcv_data);
	reading->xmit_pkts = cl_ntoh32(wire_read->xmit_pkts);
	reading->rcv_pkts = cl_ntoh32(wire_read->rcv_pkts);
	reading->unicast_xmit_pkts = 0;
	reading->unicast_rcv_pkts = 0;
	reading->multicast_xmit_pkts = 0;
	reading->multicast_rcv_pkts = 0;
	reading->time = time(NULL);
}
コード例 #5
0
static ib_api_status_t
__osmv_dispatch_accept_seg(IN osm_bind_handle_t h_bind,
			   IN osmv_txn_ctx_t * p_txn, IN const ib_mad_t * p_mad)
{
	ib_api_status_t ret = IB_SUCCESS;
	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
	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;
	uint64_t tid = osmv_txn_get_tid(p_txn);

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	if (seg_num != p_recv_ctx->expected_seg) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"TID 0x%" PRIx64 ": can't accept this segment (%d) - "
			"this is a Go-Back-N implementation\n", tid, seg_num);
		return IB_INSUFFICIENT_RESOURCES;
	}

	/* Store the packet's copy in the reassembly list.
	 * Promote the expected segment counter.
	 */
	ret = osmv_rmpp_recv_ctx_store_mad_seg(p_recv_ctx, (uint8_t *) p_mad);
	if (IB_SUCCESS != ret) {
		return ret;
	}

	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"TID 0x%" PRIx64 ": segment %d accepted\n", tid, seg_num);
	p_recv_ctx->expected_seg = seg_num + 1;

	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
	return IB_SUCCESS;
}
コード例 #6
0
/**********************************************************************
 * Fill in the various DB objects from their wire counter parts
 **********************************************************************/
void
perfmgr_db_fill_err_read(ib_port_counters_t * wire_read,
			 perfmgr_db_err_reading_t * reading,
			 boolean_t xmit_wait_sup)
{
	reading->symbol_err_cnt = cl_ntoh16(wire_read->symbol_err_cnt);
	reading->link_err_recover = wire_read->link_err_recover;
	reading->link_downed = wire_read->link_downed;
	reading->rcv_err = cl_ntoh16(wire_read->rcv_err);
	reading->rcv_rem_phys_err = cl_ntoh16(wire_read->rcv_rem_phys_err);
	reading->rcv_switch_relay_err =
	    cl_ntoh16(wire_read->rcv_switch_relay_err);
	reading->xmit_discards = cl_ntoh16(wire_read->xmit_discards);
	reading->xmit_constraint_err = wire_read->xmit_constraint_err;
	reading->rcv_constraint_err = wire_read->rcv_constraint_err;
	reading->link_integrity =
	    PC_LINK_INT(wire_read->link_int_buffer_overrun);
	reading->buffer_overrun =
	    PC_BUF_OVERRUN(wire_read->link_int_buffer_overrun);
	reading->vl15_dropped = cl_ntoh16(wire_read->vl15_dropped);
	if (xmit_wait_sup)
		reading->xmit_wait = cl_ntoh32(wire_read->xmit_wait);
	else
		reading->xmit_wait = 0;
	reading->time = time(NULL);
}
コード例 #7
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);
}
コード例 #8
0
ファイル: osm_sa.c プロジェクト: Cai900205/test
static void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt)
{
	FILE *file = ((struct opensm_dump_context *)cxt)->file;
	osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
	ib_inform_info_record_t *p_iir = &p_infr->inform_record;

	fprintf(file, "InformInfo Record:"
		" subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64
		" subscriber_enum=0x%x"
		" InformInfo:"
		" gid=0x%016" PRIx64 ":0x%016" PRIx64
		" lid_range_begin=0x%x"
		" lid_range_end=0x%x"
		" is_generic=0x%x"
		" subscribe=0x%x"
		" trap_type=0x%x"
		" trap_num=0x%x"
		" qpn_resp_time_val=0x%x"
		" node_type=0x%06x"
		" rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x"
		" remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x"
		"\n\n",
		cl_ntoh64(p_iir->subscriber_gid.unicast.prefix),
		cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id),
		cl_ntoh16(p_iir->subscriber_enum),
		cl_ntoh64(p_iir->inform_info.gid.unicast.prefix),
		cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id),
		cl_ntoh16(p_iir->inform_info.lid_range_begin),
		cl_ntoh16(p_iir->inform_info.lid_range_end),
		p_iir->inform_info.is_generic,
		p_iir->inform_info.subscribe,
		cl_ntoh16(p_iir->inform_info.trap_type),
		cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
		cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val),
		cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)),
		cl_ntoh16(p_infr->report_addr.dest_lid),
		p_infr->report_addr.path_bits,
		p_infr->report_addr.static_rate,
		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp),
		cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey),
		p_infr->report_addr.addr_type.gsi.pkey_ix,
		p_infr->report_addr.addr_type.gsi.service_level);
}
コード例 #9
0
ファイル: osm_vendor_ts.c プロジェクト: 2014-class/freerouter
/**********************************************************************
 * Poller thread:
 * Always receive 256byte mads from the devcie file
 **********************************************************************/
void __osm_vendor_ts_poller(IN void *p_ptr)
{
	int ts_ret_code;
	struct ib_mad mad;
	osm_mad_addr_t mad_addr;
	osm_ts_bind_info_t *const p_bind = (osm_ts_bind_info_t *) p_ptr;

	OSM_LOG_ENTER(p_bind->p_vend->p_log);
	/* we set the type of cancelation for this thread */
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	while (1) {
		/* we read one mad at a time and pass it to the read callback function */
		ts_ret_code = read(p_bind->ul_dev_fd, &mad, sizeof(mad));
		if (ts_ret_code != sizeof(mad)) {
			osm_log(p_bind->p_vend->p_log, OSM_LOG_ERROR,
				"__osm_vendor_ts_poller: ERR 5003: "
				"error with read, bytes = %d, errno = %d\n",
				ts_ret_code, errno);
		} else {
			osm_log(p_bind->p_vend->p_log, OSM_LOG_DEBUG,
				"__osm_vendor_ts_poller: "
				"MAD QPN:%d SLID:0x%04x class:0x%02x "
				"__osm_vendor_ts_poller:0x%02x attr:0x%04x status:0x%04x "
				"__osm_vendor_ts_poller:0x%016" PRIx64 "\n",
				cl_ntoh32(mad.dqpn),
				cl_ntoh16(mad.slid),
				mad.mgmt_class,
				mad.r_method,
				cl_ntoh16(mad.attribute_id),
				cl_ntoh16(mad.status),
				cl_ntoh64(mad.transaction_id));

			/* first arrange an address */
			__osm_ts_conv_mad_rcv_desc_to_osm_addr(p_bind->p_vend,
							       &mad,
							       (((ib_mad_t *) &
								 mad)->
								mgmt_class ==
								IB_MCLASS_SUBN_LID)
							       ||
							       (((ib_mad_t *) &
								 mad)->
								mgmt_class ==
								IB_MCLASS_SUBN_DIR),
							       &mad_addr);

			/* call the receiver callback */
			/* HACK: this should be replaced with a call to the RMPP Assembly ... */
			__osm_ts_rcv_callback(p_bind, &mad_addr, 256, &mad);
		}
	}

	OSM_LOG_EXIT(p_bind->p_vend->p_log);
}
コード例 #10
0
ファイル: osm_lin_fwd_rcv.c プロジェクト: Cai900205/test
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);
}
コード例 #11
0
static void
__osmv_dispatch_send_ack(IN osm_bind_handle_t h_bind,
			 IN const ib_mad_t * p_req_mad,
			 IN osmv_txn_ctx_t * p_txn,
			 IN const osm_mad_addr_t * p_mad_addr)
{
	osmv_rmpp_recv_ctx_t *p_recv_ctx = osmv_txn_get_rmpp_recv_ctx(p_txn);

	/* ACK the segment # that was accepted */
	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_req_mad)->seg_num);

	/* NOTE! The receiver can publish the New Window Last (NWL) value
	 * that is greater than the total number of segments to be sent.
	 * It's the sender's responsibility to compute the correct number
	 * of segments to send in the next burst.
	 */
	uint32_t nwl = p_recv_ctx->expected_seg + OSMV_RMPP_RECV_WIN - 1;

	osmv_rmpp_send_ack(h_bind, p_req_mad, seg_num, nwl, p_mad_addr);
}
コード例 #12
0
static void
__osmv_ibms_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
				 IN struct _ibms_mad_addr *p_ibms_addr,
				 IN uint8_t is_smi,
				 OUT osm_mad_addr_t * p_osm_addr)
{
	memset(p_osm_addr, 0, sizeof(osm_mad_addr_t));
	p_osm_addr->dest_lid = cl_hton16(p_ibms_addr->slid);
	p_osm_addr->static_rate = 0;
	p_osm_addr->path_bits = 0;
	if (is_smi) {
		/* SMI */
		p_osm_addr->addr_type.smi.source_lid =
		    cl_hton16(p_ibms_addr->slid);
		p_osm_addr->addr_type.smi.port_num = 1;	/* TODO add if required p_ibms_addr->port; */
	} else {
		/* GSI */
		p_osm_addr->addr_type.gsi.remote_qp =
		    cl_ntoh32(p_ibms_addr->sqpn);
		p_osm_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
		p_osm_addr->addr_type.gsi.pkey_ix = p_ibms_addr->pkey_index;
		p_osm_addr->addr_type.gsi.service_level = p_ibms_addr->sl;

		p_osm_addr->addr_type.gsi.global_route = FALSE;
		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
		/*
		   if (p_osm_addr->addr_type.gsi.global_route)
		   {
		   p_osm_addr->addr_type.gsi.grh_info.ver_class_flow =
		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
		   p_rcv_desc->grh.traffic_class,
		   p_rcv_desc->grh.flow_label);
		   p_osm_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
		   memcpy(&p_osm_addr->addr_type.gsi.grh_info.src_gid.raw,
		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
		   memcpy(&p_osm_addr->addr_type.gsi.grh_info.dest_gid.raw,
		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
		   }
		 */
	}
}
コード例 #13
0
static void
__osmv_TOPSPIN_osm_addr_to_mad_addr(IN const osm_mad_addr_t * p_mad_addr,
				    IN uint8_t is_smi, OUT struct ib_mad *p_mad)
{

	/* For global destination or Multicast address: */
	p_mad->dlid = cl_ntoh16(p_mad_addr->dest_lid);
	p_mad->sl = p_mad_addr->addr_type.gsi.service_level;
	if (is_smi) {
		p_mad->sqpn = 0;
		p_mad->dqpn = 0;
	} else {
		p_mad->sqpn = 1;
		p_mad->dqpn = cl_ntoh32(p_mad_addr->addr_type.gsi.remote_qp);
	}
	/*
	   HACK we limit to the first PKey Index assuming it will
	   always be the default PKey
	 */
	p_mad->pkey_index = 0;
}
コード例 #14
0
static void
__osmv_TOPSPIN_mad_addr_to_osm_addr(IN osm_vendor_t const *p_vend,
				    IN struct ib_mad *p_mad,
				    IN uint8_t is_smi,
				    OUT osm_mad_addr_t * p_mad_addr)
{
	p_mad_addr->dest_lid = cl_hton16(p_mad->slid);
	p_mad_addr->static_rate = 0;
	p_mad_addr->path_bits = 0;
	if (is_smi) {
		/* SMI */
		p_mad_addr->addr_type.smi.source_lid = cl_hton16(p_mad->slid);
		p_mad_addr->addr_type.smi.port_num = p_mad->port;
	} else {
		/* GSI */
		p_mad_addr->addr_type.gsi.remote_qp = cl_ntoh32(p_mad->sqpn);
		p_mad_addr->addr_type.gsi.remote_qkey = IB_QP1_WELL_KNOWN_Q_KEY;
		/*  There is a TAVOR limitation that only one P_KEY is supported per */
		/*  QP - so QP1 must use IB_DEFAULT_PKEY */
		p_mad_addr->addr_type.gsi.pkey_ix = p_mad->pkey_index;
		p_mad_addr->addr_type.gsi.service_level = p_mad->sl;

		p_mad_addr->addr_type.gsi.global_route = FALSE;
		/* copy the GRH data if relevant - TopSpin imp doesnt relate to GRH!!! */
		/*
		   if (p_mad_addr->addr_type.gsi.global_route)
		   {
		   p_mad_addr->addr_type.gsi.grh_info.ver_class_flow =
		   ib_grh_set_ver_class_flow(p_rcv_desc->grh.IP_version,
		   p_rcv_desc->grh.traffic_class,
		   p_rcv_desc->grh.flow_label);
		   p_mad_addr->addr_type.gsi.grh_info.hop_limit =  p_rcv_desc->grh.hop_limit;
		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.src_gid.raw,
		   &p_rcv_desc->grh.sgid, sizeof(ib_net64_t));
		   memcpy(&p_mad_addr->addr_type.gsi.grh_info.dest_gid.raw,
		   p_rcv_desc->grh.dgid,  sizeof(ib_net64_t));
		   }
		 */
	}
}
コード例 #15
0
static ib_api_status_t mpr_rcv_get_path_parms(IN osm_sa_t * sa,
					      IN const ib_multipath_rec_t *
					      p_mpr,
					      IN const osm_alias_guid_t * p_src_alias_guid,
					      IN const osm_alias_guid_t * p_dest_alias_guid,
					      IN const uint16_t dest_lid_ho,
					      IN const ib_net64_t comp_mask,
					      OUT osm_path_parms_t * p_parms)
{
	const osm_node_t *p_node;
	const osm_physp_t *p_physp, *p_physp0;
	const osm_physp_t *p_src_physp;
	const osm_physp_t *p_dest_physp;
	const osm_prtn_t *p_prtn = NULL;
	const ib_port_info_t *p_pi, *p_pi0;
	ib_slvl_table_t *p_slvl_tbl;
	ib_api_status_t status = IB_SUCCESS;
	uint8_t mtu;
	uint8_t rate;
	uint8_t pkt_life;
	uint8_t required_mtu;
	uint8_t required_rate;
	ib_net16_t required_pkey;
	uint8_t required_sl;
	uint8_t required_pkt_life;
	ib_net16_t dest_lid;
	int hops = 0;
	int in_port_num = 0;
	uint8_t i;
	osm_qos_level_t *p_qos_level = NULL;
	uint16_t valid_sl_mask = 0xffff;

	OSM_LOG_ENTER(sa->p_log);

	dest_lid = cl_hton16(dest_lid_ho);

	p_dest_physp = p_dest_alias_guid->p_base_port->p_physp;
	p_physp = p_src_alias_guid->p_base_port->p_physp;
	p_src_physp = p_physp;
	p_pi = &p_physp->port_info;

	mtu = ib_port_info_get_mtu_cap(p_pi);
	rate = ib_port_info_compute_rate(p_pi,
					 p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);

	/*
	   Mellanox Tavor device performance is better using 1K MTU.
	   If required MTU and MTU selector are such that 1K is OK
	   and at least one end of the path is Tavor we override the
	   port MTU with 1K.
	 */
	if (sa->p_subn->opt.enable_quirks &&
	    sa_multipath_rec_apply_tavor_mtu_limit(p_mpr,
						   p_src_alias_guid->p_base_port,
						   p_dest_alias_guid->p_base_port,
						   comp_mask))
		if (mtu > IB_MTU_LEN_1024) {
			mtu = IB_MTU_LEN_1024;
			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
				"Optimized Path MTU to 1K for Mellanox Tavor device\n");
		}

	/*
	   Walk the subnet object from source to destination,
	   tracking the most restrictive rate and mtu values along the way...

	   If source port node is a switch, then p_physp should
	   point to the port that routes the destination lid
	 */

	p_node = osm_physp_get_node_ptr(p_physp);

	if (p_node->sw) {
		/*
		 * Source node is a switch.
		 * Make sure that p_physp points to the out port of the
		 * switch that routes to the destination lid (dest_lid_ho)
		 */
		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
		if (p_physp == 0) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4514: "
				"Can't find routing to LID %u on switch %s "
				"(GUID 0x%016"PRIx64")\n", dest_lid_ho,
				p_node->print_desc,
				cl_ntoh64(osm_node_get_node_guid(p_node)));
			status = IB_NOT_FOUND;
			goto Exit;
		}
	}

	if (sa->p_subn->opt.qos) {

		/*
		 * Whether this node is switch or CA, the IN port for
		 * the sl2vl table is 0, because this is a source node.
		 */
		p_slvl_tbl = osm_physp_get_slvl_tbl(p_physp, 0);

		/* update valid SLs that still exist on this route */
		for (i = 0; i < IB_MAX_NUM_VLS; i++) {
			if (valid_sl_mask & (1 << i) &&
			    ib_slvl_table_get(p_slvl_tbl, i) == IB_DROP_VL)
				valid_sl_mask &= ~(1 << i);
		}
		if (!valid_sl_mask) {
			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
				"All the SLs lead to VL15 on this path\n");
			status = IB_NOT_FOUND;
			goto Exit;
		}
	}

	/*
	 * Same as above
	 */
	p_node = osm_physp_get_node_ptr(p_dest_physp);

	if (p_node->sw) {
		/*
		 * if destination is switch, we want p_dest_physp to point to port 0
		 */
		p_dest_physp =
		    osm_switch_get_route_by_lid(p_node->sw, dest_lid);

		if (p_dest_physp == 0) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4515: "
				"Can't find routing to LID %u on switch %s "
				"(GUID 0x%016"PRIx64")\n", dest_lid_ho,
				p_node->print_desc,
				cl_ntoh64(osm_node_get_node_guid(p_node)));
			status = IB_NOT_FOUND;
			goto Exit;
		}

	}

	/*
	 * Now go through the path step by step
	 */

	while (p_physp != p_dest_physp) {

		int tmp_pnum = p_physp->port_num;
		p_node = osm_physp_get_node_ptr(p_physp);
		p_physp = osm_physp_get_remote(p_physp);

		if (p_physp == 0) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4505: "
				"Can't find remote phys port of %s (GUID "
				"0x%016"PRIx64") port %d "
				"while routing to LID %u",
				p_node->print_desc,
				cl_ntoh64(osm_node_get_node_guid(p_node)),
				tmp_pnum,
				dest_lid_ho);
			status = IB_ERROR;
			goto Exit;
		}

		/* update number of hops traversed */
		hops++;
		if (hops > MAX_HOPS) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4520: "
				"Path from GUID 0x%016" PRIx64 " (%s) to"
				" lid %u GUID 0x%016" PRIx64 " (%s) needs"
				" more than %d hops, max %d hops allowed\n",
				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
				p_src_physp->p_node->print_desc, dest_lid_ho,
				cl_ntoh64(osm_physp_get_port_guid
					  (p_dest_physp)),
				p_dest_physp->p_node->print_desc, hops,
				MAX_HOPS);
			status = IB_NOT_FOUND;
			goto Exit;
		}

		in_port_num = osm_physp_get_port_num(p_physp);

		/*
		   This is point to point case (no switch in between)
		 */
		if (p_physp == p_dest_physp)
			break;

		p_node = osm_physp_get_node_ptr(p_physp);

		if (!p_node->sw) {
			/*
			   There is some sort of problem in the subnet object!
			   If this isn't a switch, we should have reached
			   the destination by now!
			 */
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4503: "
				"Internal error, bad path while routing "
				"from %s (GUID: 0x%016"PRIx64") port %d "
				"to %s (GUID: 0x%016"PRIx64") port %d; "
				"ended at %s port %d\n",
				p_src_alias_guid->p_base_port->p_node->print_desc,
				cl_ntoh64(p_src_alias_guid->p_base_port->p_node->node_info.node_guid),
				p_src_alias_guid->p_base_port->p_physp->port_num,
				p_dest_alias_guid->p_base_port->p_node->print_desc,
				cl_ntoh64(p_dest_alias_guid->p_base_port->p_node->node_info.node_guid),
				p_dest_alias_guid->p_base_port->p_physp->port_num,
				p_node->print_desc,
				p_physp->port_num);
			status = IB_ERROR;
			goto Exit;
		}

		/*
		   Check parameters for the ingress port in this switch.
		 */
		p_pi = &p_physp->port_info;

		if (mtu > ib_port_info_get_mtu_cap(p_pi))
			mtu = ib_port_info_get_mtu_cap(p_pi);

		p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0);
		p_pi0 = &p_physp0->port_info;
		if (ib_path_compare_rates(rate,
					  ib_port_info_compute_rate(p_pi,
								    p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)) > 0)
			rate = ib_port_info_compute_rate(p_pi,
							 p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);

		/*
		   Continue with the egress port on this switch.
		 */
		p_physp = osm_switch_get_route_by_lid(p_node->sw, dest_lid);
		if (p_physp == 0) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4516: "
				"Dead end path on switch "
				"%s (GUID: 0x%016"PRIx64") to LID %u\n",
				p_node->print_desc,
				cl_ntoh64(osm_node_get_node_guid(p_node)),
				dest_lid_ho);
			status = IB_ERROR;
			goto Exit;
		}

		p_pi = &p_physp->port_info;

		if (mtu > ib_port_info_get_mtu_cap(p_pi))
			mtu = ib_port_info_get_mtu_cap(p_pi);

		p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_node, 0);
		p_pi0 = &p_physp0->port_info;
		if (ib_path_compare_rates(rate,
					  ib_port_info_compute_rate(p_pi,
								    p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)) > 0)
			rate = ib_port_info_compute_rate(p_pi,
							 p_pi0->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);

		if (sa->p_subn->opt.qos) {
			/*
			 * Check SL2VL table of the switch and update valid SLs
			 */
			p_slvl_tbl =
			    osm_physp_get_slvl_tbl(p_physp, in_port_num);
			for (i = 0; i < IB_MAX_NUM_VLS; i++) {
				if (valid_sl_mask & (1 << i) &&
				    ib_slvl_table_get(p_slvl_tbl,
						      i) == IB_DROP_VL)
					valid_sl_mask &= ~(1 << i);
			}
			if (!valid_sl_mask) {
				OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
					"All the SLs lead to VL15 "
					"on this path\n");
				status = IB_NOT_FOUND;
				goto Exit;
			}
		}
	}

	/*
	   p_physp now points to the destination
	 */
	p_pi = &p_physp->port_info;

	if (mtu > ib_port_info_get_mtu_cap(p_pi))
		mtu = ib_port_info_get_mtu_cap(p_pi);

	if (ib_path_compare_rates(rate,
				  ib_port_info_compute_rate(p_pi,
							    p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS)) > 0)
		rate = ib_port_info_compute_rate(p_pi,
						 p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS);

	OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
		"Path min MTU = %u, min rate = %u\n", mtu, rate);

	/*
	 * Get QoS Level object according to the MultiPath request
	 * and adjust MultiPath parameters according to QoS settings
	 */
	if (sa->p_subn->opt.qos && sa->p_subn->p_qos_policy &&
	    (p_qos_level =
	     osm_qos_policy_get_qos_level_by_mpr(sa->p_subn->p_qos_policy,
						 p_mpr, p_src_physp,
						 p_dest_physp, comp_mask))) {

		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"MultiPathRecord request matches QoS Level '%s' (%s)\n",
			p_qos_level->name,
			p_qos_level->use ? p_qos_level->use : "no description");

		if (p_qos_level->mtu_limit_set
		    && (mtu > p_qos_level->mtu_limit))
			mtu = p_qos_level->mtu_limit;

		if (p_qos_level->rate_limit_set
		    && (ib_path_compare_rates(rate, p_qos_level->rate_limit) > 0))
			rate = p_qos_level->rate_limit;

		if (p_qos_level->sl_set) {
			required_sl = p_qos_level->sl;
			if (!(valid_sl_mask & (1 << required_sl))) {
				status = IB_NOT_FOUND;
				goto Exit;
			}
		}
	}

	/*
	   Determine if these values meet the user criteria
	 */

	/* we silently ignore cases where only the MTU selector is defined */
	if ((comp_mask & IB_MPR_COMPMASK_MTUSELEC) &&
	    (comp_mask & IB_MPR_COMPMASK_MTU)) {
		required_mtu = ib_multipath_rec_mtu(p_mpr);
		switch (ib_multipath_rec_mtu_sel(p_mpr)) {
		case 0:	/* must be greater than */
			if (mtu <= required_mtu)
				status = IB_NOT_FOUND;
			break;

		case 1:	/* must be less than */
			if (mtu >= required_mtu) {
				/* adjust to use the highest mtu
				   lower then the required one */
				if (required_mtu > 1)
					mtu = required_mtu - 1;
				else
					status = IB_NOT_FOUND;
			}
			break;

		case 2:	/* exact match */
			if (mtu < required_mtu)
				status = IB_NOT_FOUND;
			else
				mtu = required_mtu;
			break;

		case 3:	/* largest available */
			/* can't be disqualified by this one */
			break;

		default:
			/* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
			CL_ASSERT(FALSE);
			status = IB_ERROR;
			break;
		}
	}
	if (status != IB_SUCCESS)
		goto Exit;

	/* we silently ignore cases where only the Rate selector is defined */
	if ((comp_mask & IB_MPR_COMPMASK_RATESELEC) &&
	    (comp_mask & IB_MPR_COMPMASK_RATE)) {
		required_rate = ib_multipath_rec_rate(p_mpr);
		switch (ib_multipath_rec_rate_sel(p_mpr)) {
		case 0:	/* must be greater than */
			if (ib_path_compare_rates(rate, required_rate) <= 0)
				status = IB_NOT_FOUND;
			break;

		case 1:	/* must be less than */
			if (ib_path_compare_rates(rate, required_rate) >= 0) {
				/* adjust the rate to use the highest rate
				   lower then the required one */
				rate = ib_path_rate_get_prev(required_rate);
				if (!rate)
					status = IB_NOT_FOUND;
			}
			break;

		case 2:	/* exact match */
			if (ib_path_compare_rates(rate, required_rate))
				status = IB_NOT_FOUND;
			else
				rate = required_rate;
			break;

		case 3:	/* largest available */
			/* can't be disqualified by this one */
			break;

		default:
			/* if we're here, there's a bug in ib_multipath_rec_mtu_sel() */
			CL_ASSERT(FALSE);
			status = IB_ERROR;
			break;
		}
	}
	if (status != IB_SUCCESS)
		goto Exit;

	/* Verify the pkt_life_time */
	/* According to spec definition IBA 1.2 Table 205 PacketLifeTime description,
	   for loopback paths, packetLifeTime shall be zero. */
	if (p_src_alias_guid->p_base_port == p_dest_alias_guid->p_base_port)
		pkt_life = 0;	/* loopback */
	else if (p_qos_level && p_qos_level->pkt_life_set)
		pkt_life = p_qos_level->pkt_life;
	else
		pkt_life = sa->p_subn->opt.subnet_timeout;

	/* we silently ignore cases where only the PktLife selector is defined */
	if ((comp_mask & IB_MPR_COMPMASK_PKTLIFETIMESELEC) &&
	    (comp_mask & IB_MPR_COMPMASK_PKTLIFETIME)) {
		required_pkt_life = ib_multipath_rec_pkt_life(p_mpr);
		switch (ib_multipath_rec_pkt_life_sel(p_mpr)) {
		case 0:	/* must be greater than */
			if (pkt_life <= required_pkt_life)
				status = IB_NOT_FOUND;
			break;

		case 1:	/* must be less than */
			if (pkt_life >= required_pkt_life) {
				/* adjust the lifetime to use the highest possible
				   lower then the required one */
				if (required_pkt_life > 1)
					pkt_life = required_pkt_life - 1;
				else
					status = IB_NOT_FOUND;
			}
			break;

		case 2:	/* exact match */
			if (pkt_life < required_pkt_life)
				status = IB_NOT_FOUND;
			else
				pkt_life = required_pkt_life;
			break;

		case 3:	/* smallest available */
			/* can't be disqualified by this one */
			break;

		default:
			/* if we're here, there's a bug in ib_path_rec_pkt_life_sel() */
			CL_ASSERT(FALSE);
			status = IB_ERROR;
			break;
		}
	}

	if (status != IB_SUCCESS)
		goto Exit;

	/*
	 * set Pkey for this MultiPath record request
	 */

	if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
	    cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
		required_pkey =
		    osm_physp_find_common_pkey(p_src_physp, p_dest_physp,
					       sa->p_subn->opt.allow_both_pkeys);

	else if (comp_mask & IB_MPR_COMPMASK_PKEY) {
		/*
		 * MPR request has a specific pkey:
		 * Check that source and destination share this pkey.
		 * If QoS level has pkeys, check that this pkey exists
		 * in the QoS level pkeys.
		 * MPR returned pkey is the requested pkey.
		 */
		required_pkey = p_mpr->pkey;
		if (!osm_physp_share_this_pkey
		    (p_src_physp, p_dest_physp, required_pkey,
		     sa->p_subn->opt.allow_both_pkeys)) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4518: "
				"Ports src 0x%016"PRIx64" (%s port %d) "
				"and dst 0x%016"PRIx64" (%s port %d) "
				"do not share the specified PKey 0x%04x\n",
				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
				p_src_physp->p_node->print_desc,
				p_src_physp->port_num,
				cl_ntoh64(osm_physp_get_port_guid
					  (p_dest_physp)),
				p_dest_physp->p_node->print_desc,
				p_dest_physp->port_num,
				cl_ntoh16(required_pkey));
			status = IB_NOT_FOUND;
			goto Exit;
		}
		if (p_qos_level && p_qos_level->pkey_range_len &&
		    !osm_qos_level_has_pkey(p_qos_level, required_pkey)) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451C: "
				"Ports src 0x%016"PRIx64" (%s port %d) "
				"and dst 0x%016"PRIx64" (%s port %d) "
				"do not share specified PKey (0x%04x) as "
				"defined by QoS level \"%s\"\n",
				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
				p_src_physp->p_node->print_desc,
				p_src_physp->port_num,
				cl_ntoh64(osm_physp_get_port_guid
					  (p_dest_physp)),
				p_dest_physp->p_node->print_desc,
				p_dest_physp->port_num,
				cl_ntoh16(required_pkey),
				p_qos_level->name);
			status = IB_NOT_FOUND;
			goto Exit;
		}

	} else if (p_qos_level && p_qos_level->pkey_range_len) {
		/*
		 * MPR request doesn't have a specific pkey, but QoS level
		 * has pkeys - get shared pkey from QoS level pkeys
		 */
		required_pkey = osm_qos_level_get_shared_pkey(p_qos_level,
							      p_src_physp,
							      p_dest_physp,
							      sa->p_subn->opt.allow_both_pkeys);
		if (!required_pkey) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451D: "
				"Ports src 0x%016"PRIx64" (%s port %d) "
				"and dst 0x%016"PRIx64" (%s port %d) "
				"do not share a PKey as defined by QoS "
				"level \"%s\"\n",
				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
				p_src_physp->p_node->print_desc,
				p_src_physp->port_num,
				cl_ntoh64(osm_physp_get_port_guid
					  (p_dest_physp)),
				p_dest_physp->p_node->print_desc,
				p_dest_physp->port_num,
				p_qos_level->name);
			status = IB_NOT_FOUND;
			goto Exit;
		}

	} else {
		/*
		 * Neither MPR request nor QoS level have pkey.
		 * Just get any shared pkey.
		 */
		required_pkey =
		    osm_physp_find_common_pkey(p_src_physp, p_dest_physp,
					       sa->p_subn->opt.allow_both_pkeys);
		if (!required_pkey) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4519: "
				"Ports src 0x%016"PRIx64" (%s port %d) "
				"and dst 0x%016"PRIx64" (%s port %d) "
				"do not have any shared PKeys\n",
				cl_ntoh64(osm_physp_get_port_guid(p_src_physp)),
				p_src_physp->p_node->print_desc,
				p_src_physp->port_num,
				cl_ntoh64(osm_physp_get_port_guid
					  (p_dest_physp)),
				p_dest_physp->p_node->print_desc,
				p_dest_physp->port_num);
			status = IB_NOT_FOUND;
			goto Exit;
		}
	}

	if (required_pkey) {
		p_prtn =
		    (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
					       required_pkey &
					       cl_ntoh16((uint16_t) ~ 0x8000));
		if (p_prtn ==
		    (osm_prtn_t *) cl_qmap_end(&sa->p_subn->prtn_pkey_tbl))
			p_prtn = NULL;
	}

	/*
	 * Set MultiPathRecord SL.
	 */

	if (comp_mask & IB_MPR_COMPMASK_SL) {
		/*
		 * Specific SL was requested
		 */
		required_sl = ib_multipath_rec_sl(p_mpr);

		if (p_qos_level && p_qos_level->sl_set &&
		    p_qos_level->sl != required_sl) {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451E: "
				"QoS constraints: required MultiPathRecord SL "
				"(%u) doesn't match QoS policy \"%s\" SL (%u) "
				"[%s port %d <-> %s port %d]\n", required_sl,
				p_qos_level->name,
				p_qos_level->sl,
				p_src_alias_guid->p_base_port->p_node->print_desc,
				p_src_alias_guid->p_base_port->p_physp->port_num,
				p_dest_alias_guid->p_base_port->p_node->print_desc,
				p_dest_alias_guid->p_base_port->p_physp->port_num);
			status = IB_NOT_FOUND;
			goto Exit;
		}

	} else if (p_qos_level && p_qos_level->sl_set) {
		/*
		 * No specific SL was requested,
		 * but there is an SL in QoS level.
		 */
		required_sl = p_qos_level->sl;

		if (required_pkey && p_prtn && p_prtn->sl != p_qos_level->sl)
			OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
				"QoS level SL (%u) overrides partition SL (%u)\n",
				p_qos_level->sl, p_prtn->sl);

	} else if (required_pkey) {
		/*
		 * No specific SL in request or in QoS level - use partition SL
		 */
		p_prtn =
		    (osm_prtn_t *) cl_qmap_get(&sa->p_subn->prtn_pkey_tbl,
					       required_pkey &
					       cl_ntoh16((uint16_t) ~ 0x8000));
		if (!p_prtn) {
			required_sl = OSM_DEFAULT_SL;
			/* this may be possible when pkey tables are created somehow in
			   previous runs or things are going wrong here */
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451A: "
				"No partition found for PKey 0x%04x - "
				"using default SL %d "
				"[%s port %d <-> %s port %d]\n",
				cl_ntoh16(required_pkey), required_sl,
				p_src_alias_guid->p_base_port->p_node->print_desc,
				p_src_alias_guid->p_base_port->p_physp->port_num,
				p_dest_alias_guid->p_base_port->p_node->print_desc,
				p_dest_alias_guid->p_base_port->p_physp->port_num);
		} else
			required_sl = p_prtn->sl;

	} else if (sa->p_subn->opt.qos) {
		if (valid_sl_mask & (1 << OSM_DEFAULT_SL))
			required_sl = OSM_DEFAULT_SL;
		else {
			for (i = 0; i < IB_MAX_NUM_VLS; i++)
				if (valid_sl_mask & (1 << i))
					break;
			required_sl = i;
		}
	} else
		required_sl = OSM_DEFAULT_SL;

	if (sa->p_subn->opt.qos && !(valid_sl_mask & (1 << required_sl))) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 451F: "
			"Selected SL (%u) leads to VL15 "
			"[%s port %d <-> %s port %d]\n",
			required_sl,
			p_src_alias_guid->p_base_port->p_node->print_desc,
			p_src_alias_guid->p_base_port->p_physp->port_num,
			p_dest_alias_guid->p_base_port->p_node->print_desc,
			p_dest_alias_guid->p_base_port->p_physp->port_num);
		status = IB_NOT_FOUND;
		goto Exit;
	}

	/* reset pkey when raw traffic */
	if (comp_mask & IB_MPR_COMPMASK_RAWTRAFFIC &&
	    cl_ntoh32(p_mpr->hop_flow_raw) & (1 << 31))
		required_pkey = 0;

	p_parms->mtu = mtu;
	p_parms->rate = rate;
	p_parms->pkey = required_pkey;
	p_parms->pkt_life = pkt_life;
	p_parms->sl = required_sl;
	p_parms->hops = hops;

	OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "MultiPath params:"
		" mtu = %u, rate = %u, packet lifetime = %u,"
		" pkey = 0x%04X, sl = %u, hops = %u\n", mtu, rate,
		pkt_life, cl_ntoh16(required_pkey), required_sl, hops);

Exit:
	OSM_LOG_EXIT(sa->p_log);
	return status;
}
コード例 #16
0
ファイル: osm_req.c プロジェクト: FreeBSDFoundation/freebsd
/**********************************************************************
  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;
}
コード例 #17
0
static void get_pkey_table(IN osm_log_t * p_log, IN osm_sm_t * sm,
			   IN osm_node_t * p_node, IN osm_physp_t * p_physp)
{

	osm_madw_context_t context;
	ib_api_status_t status;
	osm_dr_path_t path;
	osm_physp_t *physp0;
	ib_net64_t m_key;
	uint8_t port_num;
	uint16_t block_num, max_blocks;
	uint32_t attr_mod_ho;

	OSM_LOG_ENTER(p_log);

	path = *osm_physp_get_dr_path_ptr(p_physp);

	context.pkey_context.node_guid = osm_node_get_node_guid(p_node);
	context.pkey_context.port_guid = osm_physp_get_port_guid(p_physp);
	context.pkey_context.set_method = FALSE;

	port_num = p_physp->port_num;

	if (!p_node->sw || port_num == 0)
		/* The maximum blocks is defined by the node info partition cap
		   for CA, router, and switch management ports. */
		max_blocks =
		    (cl_ntoh16(p_node->node_info.partition_cap) +
		     IB_NUM_PKEY_ELEMENTS_IN_BLOCK - 1)
		    / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
	else {
		/* This is a switch, and not a management port. The maximum blocks
		   is defined in the switch info partition enforcement cap. */

		/* Check for IBM eHCA firmware defect in reporting partition enforcement cap */
		if (cl_ntoh32(ib_node_info_get_vendor_id(&p_node->node_info)) ==
		    IBM_VENDOR_ID)
			p_node->sw->switch_info.enforce_cap = 0;

		/* Bail out if this is a switch with no partition enforcement capability */
		if (cl_ntoh16(p_node->sw->switch_info.enforce_cap) == 0)
			goto Exit;

		max_blocks = (cl_ntoh16(p_node->sw->switch_info.enforce_cap) +
			      IB_NUM_PKEY_ELEMENTS_IN_BLOCK -
			      1) / IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
	}

	p_physp->pkeys.rcv_blocks_cnt = max_blocks;
	for (block_num = 0; block_num < max_blocks; block_num++) {
		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
		    osm_physp_get_port_num(p_physp) == 0) {
			attr_mod_ho = block_num;
			m_key = ib_port_info_get_m_key(&p_physp->port_info);
		} else {
			attr_mod_ho = block_num | (port_num << 16);
			physp0 = osm_node_get_physp_ptr(p_node, 0);
			m_key = ib_port_info_get_m_key(&physp0->port_info);
		}
		status = osm_req_get(sm, &path, IB_MAD_ATTR_P_KEY_TABLE,
				     cl_hton32(attr_mod_ho), FALSE,
				     m_key, CL_DISP_MSGID_NONE, &context);

		if (status != IB_SUCCESS) {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0F12: "
				"Failure initiating PKeyTable request (%s)\n",
				ib_get_err_str(status));
			goto Exit;
		}
	}

Exit:
	OSM_LOG_EXIT(p_log);
}
コード例 #18
0
/* //////////////////////////////////////////////////////////////////////// */
ib_api_status_t
osm_vendor_send(IN osm_bind_handle_t h_bind,
		IN osm_vend_wrap_t * const p_vend_wrap,
		IN osm_mad_addr_t * const p_mad_addr,
		IN ib_mad_t * const p_mad,
		IN void *transaction_context, IN boolean_t const resp_expected)
{
	FSTATUS Status;

	MadAddrStruct destAddr = { 0 };

	mad_bind_info_t *p_mad_bind_info;
	trans_context_t *p_trans_context;

	umadt_obj_t *p_umadt_obj = NULL;

	uint32_t mad_count = 0;
	MadtStruct *p_madt_struct = NULL;
	uint32_t i;
	uint32_t num_mads = 0;
	uint32_t seg_num = 0;
	uint8_t *p_frag_data = NULL;
	ib_sa_mad_t_vM3 *p_sa_mad = NULL;

	CL_ASSERT(h_bind);
	p_mad_bind_info = (mad_bind_info_t *) h_bind;
	p_umadt_obj = p_mad_bind_info->p_umadt_obj;

	/*  sanity check */
	CL_ASSERT(p_umadt_obj);
	CL_ASSERT(p_umadt_obj->init_done);
	CL_ASSERT(__valid_mad_handle(p_mad_bind_info));
	CL_ASSERT(p_vend_wrap);
	CL_ASSERT(p_mad_addr);
	CL_ASSERT(p_mad);
	/* CL_ASSERT( (ib_mad_t*)&p_vend_wrap->p_madt_struct->IBMad == p_mad ); */

	/*  */
	/*  based on the class, fill out the address info */
	/*  */
	destAddr.DestLid = p_mad_addr->dest_lid;
	destAddr.PathBits = p_mad_addr->path_bits;
	destAddr.StaticRate = p_mad_addr->static_rate;

	if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
	    p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
		CL_ASSERT(p_mad_addr->addr_type.smi.source_lid);
		destAddr.AddrType.Smi.SourceLid =
		    p_mad_addr->addr_type.smi.source_lid;
	} else {
		destAddr.AddrType.Gsi.RemoteQpNumber =
		    p_mad_addr->addr_type.gsi.remote_qp;
		destAddr.AddrType.Gsi.RemoteQkey =
		    p_mad_addr->addr_type.gsi.remote_qkey;
		destAddr.AddrType.Gsi.PKey = OSM_DEFAULT_PKEY;
		destAddr.AddrType.Gsi.ServiceLevel =
		    p_mad_addr->addr_type.gsi.service_level;
		destAddr.AddrType.Gsi.GlobalRoute =
		    p_mad_addr->addr_type.gsi.global_route;
		/* destAddr.AddrType.Gsi.GRHInfo = p_mad_addr->addr_type.gsi.grh_info; */
	}
	p_mad->trans_id = cl_ntoh64(p_mad->trans_id) << 24;

	/*  */
	/*  Create a transaction context for this send and save the TID and client context. */
	/*  */

	if (resp_expected) {
		p_trans_context = malloc(sizeof(trans_context_t));
		CL_ASSERT(p_trans_context);

		memset(p_trans_context, 0, sizeof(trans_context_t));
		p_trans_context->trans_id = p_mad->trans_id;
		p_trans_context->context = transaction_context;
		p_trans_context->sent_time = cl_get_time_stamp();

		cl_spinlock_acquire(&p_mad_bind_info->trans_ctxt_lock);
		cl_qlist_insert_tail(&p_mad_bind_info->trans_ctxt_list,
				     &p_trans_context->list_item);
		cl_spinlock_release(&p_mad_bind_info->trans_ctxt_lock);
	}

	if (p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_LID ||
	    p_mad_bind_info->umadt_reg_class.ClassId == IB_MCLASS_SUBN_DIR) {
		/*  Get one mad from uMadt */
		mad_count = 1;
		Status =
		    p_umadt_obj->uMadtInterface.
		    uMadtGetSendMad(p_mad_bind_info->umadt_handle, &mad_count,
				    &p_madt_struct);

		if (Status != FSUCCESS || p_madt_struct == NULL) {
			return IB_ERROR;
		}

		/*  No Segmentation required */
		memcpy(&p_madt_struct->IBMad, p_mad, MAD_BLOCK_SIZE);

		/*  Post the MAD */

		Status =
		    p_umadt_obj->uMadtInterface.uMadtPostSend(p_mad_bind_info->
							      umadt_handle,
							      p_madt_struct,
							      &destAddr);
		if (Status != FSUCCESS) {
			printf("uMadtPostSendMad: Status  = <%d>\n", Status);
			return IB_ERROR;
		}

		/*  Release send MAD */
		Status =
		    p_umadt_obj->uMadtInterface.
		    uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
					p_madt_struct);
		if (Status != FSUCCESS) {
			printf("uMadtReleaseSendMad: Status  = <%d>\n", Status);
			return IB_ERROR;
		}
	} else {

		/*  */
		/*  Segment the MAD, get the required send mads from uMadt and post the MADs. */
		/*  */
		uint32_t payload_len;

		payload_len =
		    cl_ntoh32(((ib_sa_mad_t_vM3 *) p_mad)->payload_len);
		num_mads = payload_len / IB_SA_DATA_SIZE;
		if (payload_len % IB_SA_DATA_SIZE != 0) {
			num_mads++;	/*  Get one additional mad for the remainder */
		}
		for (i = 0; i < num_mads; i++) {
			/*  Get one mad from uMadt */
			mad_count = 1;
			Status =
			    p_umadt_obj->uMadtInterface.
			    uMadtGetSendMad(p_mad_bind_info->umadt_handle,
					    &mad_count, &p_madt_struct);

			if (Status != FSUCCESS || p_madt_struct == NULL) {
				return IB_ERROR;
			}
			/*  Copy client MAD into uMadt's MAD. */
			if (i == 0) {	/*  First Packet */
				/*  Since this is the first MAD, copy the entire MAD_SIZE */
				memcpy(&p_madt_struct->IBMad, p_mad,
				       MAD_BLOCK_SIZE);

				p_frag_data =
				    (uint8_t *) p_mad + MAD_BLOCK_SIZE;

				p_sa_mad =
				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
				if (num_mads == 1) {	/*  Only one Packet */
					p_sa_mad->seg_num = 0;
					p_sa_mad->frag_flag = 5;	/*  Set bit 0 for first pkt and b4 for last pkt */
					/*  the payload length gets copied with the mad header above */
				} else {	/*  More than one packet in this response */

					seg_num = 1;
					p_sa_mad->seg_num =
					    cl_ntoh32(seg_num++);
					p_sa_mad->frag_flag = 1;	/*  Set bit 0 for first pkt */
					/*  the payload length gets copied with the mad header above */
				}

			} else if (i < num_mads - 1) {	/*  Not last packet */
				/*  First copy only the header */
				memcpy(&p_madt_struct->IBMad, p_mad,
				       IB_SA_MAD_HDR_SIZE);
				/*  Set the relevant fields in the SA_MAD_HEADER */
				p_sa_mad =
				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
				p_sa_mad->payload_len =
				    cl_ntoh32(IB_SA_DATA_SIZE);
				p_sa_mad->seg_num = cl_ntoh32(seg_num++);
				p_sa_mad->frag_flag = 0;
				/*  Now copy the fragmented data */
				memcpy(((uint8_t *) & p_madt_struct->IBMad) +
				       IB_SA_MAD_HDR_SIZE, p_frag_data,
				       IB_SA_DATA_SIZE);
				p_frag_data = p_frag_data + IB_SA_DATA_SIZE;

			} else if (i == num_mads - 1) {	/*  Last packet */
				/*  First copy only the header */
				memcpy(&p_madt_struct->IBMad, p_mad,
				       IB_SA_MAD_HDR_SIZE);
				/*  Set the relevant fields in the SA_MAD_HEADER */
				p_sa_mad =
				    (ib_sa_mad_t_vM3 *) & p_madt_struct->IBMad;
				p_sa_mad->seg_num = cl_ntoh32(seg_num++);
				p_sa_mad->frag_flag = 4;	/*  Set Bit 2 for last pkt */
				p_sa_mad->payload_len =
				    cl_ntoh32(cl_ntoh32
					      (((ib_sa_mad_t_vM3 *) p_mad)->
					       payload_len) % IB_SA_DATA_SIZE);
				/*  Now copy the fragmented data */
				memcpy((((uint8_t *) & p_madt_struct->IBMad)) +
				       IB_SA_MAD_HDR_SIZE, p_frag_data,
				       cl_ntoh32(p_sa_mad->payload_len));
				p_frag_data = p_frag_data + IB_SA_DATA_SIZE;

			}
			/*  Post the MAD */
			Status =
			    p_umadt_obj->uMadtInterface.
			    uMadtPostSend(p_mad_bind_info->umadt_handle,
					  p_madt_struct, &destAddr);
			if (Status != FSUCCESS) {
				printf("uMadtPostSendMad: Status  = <%d>\n",
				       Status);
				return IB_ERROR;
			}

			/*  Release send MAD */
			Status =
			    p_umadt_obj->uMadtInterface.
			    uMadtReleaseSendMad(p_mad_bind_info->umadt_handle,
						p_madt_struct);
			if (Status != FSUCCESS) {
				printf("uMadtReleaseSendMad: Status  = <%d>\n",
				       Status);
				return IB_ERROR;
			}
		}
	}
	return (IB_SUCCESS);
}
コード例 #19
0
/*********************************************************************
Received a Set(InformInfo) MAD
**********************************************************************/
static void
osm_infr_rcv_process_set_method(IN osm_sa_t * sa,
				IN osm_madw_t * const p_madw)
{
	ib_sa_mad_t *p_sa_mad;
	ib_inform_info_t *p_recvd_inform_info;
	osm_infr_t inform_info_rec;	/* actual inform record to be stored for reports */
	osm_infr_t *p_infr;
	ib_net32_t qpn;
	uint8_t resp_time_val;
	ib_api_status_t res;

	OSM_LOG_ENTER(sa->p_log);

	CL_ASSERT(p_madw);

	p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw);
	p_recvd_inform_info =
	    (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad);

#if 0
	if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG))
		osm_dump_inform_info(sa->p_log, p_recvd_inform_info,
				     OSM_LOG_DEBUG);
#endif

	/* Grab the lock */
	cl_plock_excl_acquire(sa->p_lock);

	/* define the inform record */
	inform_info_rec.inform_record.inform_info = *p_recvd_inform_info;

	/* following C13-32.1.2 Tbl 120: we only copy the source address vector */
	inform_info_rec.report_addr = p_madw->mad_addr;

	/* we will need to know the mad srvc to send back through */
	inform_info_rec.h_bind = p_madw->h_bind;
	inform_info_rec.sa = sa;

	/* update the subscriber GID according to mad address */
	res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr,
				      &inform_info_rec.inform_record.
				      subscriber_gid);
	if (res != IB_SUCCESS) {
		cl_plock_release(sa->p_lock);

		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
			"Subscribe Request from unknown LID: %u\n",
			cl_ntoh16(p_madw->mad_addr.dest_lid));
		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
		goto Exit;
	}

	/* HACK: enum is always 0 (currently) */
	inform_info_rec.inform_record.subscriber_enum = 0;

	/* Subscribe values above 1 are undefined */
	if (p_recvd_inform_info->subscribe > 1) {
		cl_plock_release(sa->p_lock);

		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 "
			"Invalid subscribe: %d\n",
			p_recvd_inform_info->subscribe);
		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
		goto Exit;
	}

	/*
	 * MODIFICATIONS DONE ON INCOMING REQUEST:
	 *
	 * QPN:
	 * Internally we keep the QPN field of the InformInfo updated
	 * so we can simply compare it in the record - when finding such.
	 */
	if (p_recvd_inform_info->subscribe) {
		ib_inform_info_set_qpn(&inform_info_rec.inform_record.
				       inform_info,
				       inform_info_rec.report_addr.addr_type.
				       gsi.remote_qp);

		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"Subscribe Request with QPN: 0x%06X\n",
			cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi.
				  remote_qp));
	} else {
		ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v.
						 generic.qpn_resp_time_val,
						 &qpn, &resp_time_val);

		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"UnSubscribe Request with QPN: 0x%06X\n",
			cl_ntoh32(qpn));
	}

	/* If record exists with matching InformInfo */
	p_infr =
	    osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec);

	/* check to see if the request was for subscribe */
	if (p_recvd_inform_info->subscribe) {
		/* validate the request for a new or update InformInfo */
		if (__validate_infr(sa, &inform_info_rec) != TRUE) {
			cl_plock_release(sa->p_lock);

			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: "
				"Failed to validate a new inform object\n");

			/* o13-13.1.1: we need to set the subscribe bit to 0 */
			p_recvd_inform_info->subscribe = 0;
			osm_sa_send_error(sa, p_madw,
					  IB_SA_MAD_STATUS_REQ_INVALID);
			goto Exit;
		}

		/* ok - we can try and create a new entry */
		if (p_infr == NULL) {
			/* Create the instance of the osm_infr_t object */
			p_infr = osm_infr_new(&inform_info_rec);
			if (p_infr == NULL) {
				cl_plock_release(sa->p_lock);

				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: "
					"Failed to create a new inform object\n");

				/* o13-13.1.1: we need to set the subscribe bit to 0 */
				p_recvd_inform_info->subscribe = 0;
				osm_sa_send_error(sa, p_madw,
						  IB_SA_MAD_STATUS_NO_RESOURCES);
				goto Exit;
			}

			/* Add this new osm_infr_t object to subnet object */
			osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr);
		} else
			/* Update the old instance of the osm_infr_t object */
			p_infr->inform_record = inform_info_rec.inform_record;
	/* We got an UnSubscribe request */
	} else if (p_infr == NULL) {
		cl_plock_release(sa->p_lock);

		/* No Such Item - So Error */
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: "
			"Failed to UnSubscribe to non existing inform object\n");

		/* o13-13.1.1: we need to set the subscribe bit to 0 */
		p_recvd_inform_info->subscribe = 0;
		osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID);
		goto Exit;
	} else
		/* Delete this object from the subnet list of informs */
		osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr);

	cl_plock_release(sa->p_lock);

	/* send the success response */
	__osm_infr_rcv_respond(sa, p_madw);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
コード例 #20
0
ファイル: osm_dump.c プロジェクト: chu11/opensm-snapshot
static void dump_topology_node(cl_map_item_t * item, FILE * file, void *cxt)
{
	osm_node_t *p_node = (osm_node_t *) item;
	uint32_t cPort;
	osm_node_t *p_nbnode;
	osm_physp_t *p_physp, *p_default_physp, *p_rphysp;
	uint8_t link_speed_act;
	const char *link_speed_act_str;

	if (!p_node->node_info.num_ports)
		return;

	for (cPort = 1; cPort < osm_node_get_num_physp(p_node); cPort++) {
		uint8_t port_state;

		p_physp = osm_node_get_physp_ptr(p_node, cPort);
		if (!p_physp)
			continue;

		p_rphysp = p_physp->p_remote_physp;
		if (!p_rphysp)
			continue;

		CL_ASSERT(cPort == p_physp->port_num);

		if (p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
			p_default_physp = osm_node_get_physp_ptr(p_node, 0);
		else
			p_default_physp = p_physp;

		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
			" VenID:%06X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
			p_node->node_info.node_type == IB_NODE_TYPE_SWITCH ?
			"SW" : p_node->node_info.node_type ==
			IB_NODE_TYPE_CA ? "CA" : p_node->node_info.node_type ==
			IB_NODE_TYPE_ROUTER ? "Rt" : "**",
			p_default_physp->port_info.base_lid ==
			p_default_physp->port_info.
			master_sm_base_lid ? "-SM" : "",
			p_node->node_info.num_ports,
			cl_ntoh64(p_node->node_info.sys_guid),
			cl_ntoh64(p_node->node_info.node_guid),
			cl_ntoh64(p_physp->port_guid),
			cl_ntoh32(ib_node_info_get_vendor_id
				  (&p_node->node_info)),
			cl_ntoh16(p_node->node_info.device_id),
			cl_ntoh32(p_node->node_info.revision),
			p_node->print_desc,
			cl_ntoh16(p_default_physp->port_info.base_lid), cPort);

		p_nbnode = p_rphysp->p_node;

		if (p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH)
			p_default_physp = osm_node_get_physp_ptr(p_nbnode, 0);
		else
			p_default_physp = p_rphysp;

		fprintf(file, "{ %s%s Ports:%02X SystemGUID:%016" PRIx64
			" NodeGUID:%016" PRIx64 " PortGUID:%016" PRIx64
			" VenID:%08X DevID:%04X Rev:%08X {%s} LID:%04X PN:%02X } ",
			p_nbnode->node_info.node_type == IB_NODE_TYPE_SWITCH ?
			"SW" : p_nbnode->node_info.node_type ==
			IB_NODE_TYPE_CA ? "CA" :
			p_nbnode->node_info.node_type == IB_NODE_TYPE_ROUTER ?
			"Rt" : "**",
			p_default_physp->port_info.base_lid ==
			p_default_physp->port_info.
			master_sm_base_lid ? "-SM" : "",
			p_nbnode->node_info.num_ports,
			cl_ntoh64(p_nbnode->node_info.sys_guid),
			cl_ntoh64(p_nbnode->node_info.node_guid),
			cl_ntoh64(p_rphysp->port_guid),
			cl_ntoh32(ib_node_info_get_vendor_id
				  (&p_nbnode->node_info)),
			cl_ntoh32(p_nbnode->node_info.device_id),
			cl_ntoh32(p_nbnode->node_info.revision),
			p_nbnode->print_desc,
			cl_ntoh16(p_default_physp->port_info.base_lid),
			p_rphysp->port_num);

		port_state = ib_port_info_get_port_state(&p_physp->port_info);
		link_speed_act =
		    ib_port_info_get_link_speed_active(&p_physp->port_info);
		if (link_speed_act == IB_LINK_SPEED_ACTIVE_2_5)
			link_speed_act_str = "2.5";
		else if (link_speed_act == IB_LINK_SPEED_ACTIVE_5)
			link_speed_act_str = "5";
		else if (link_speed_act == IB_LINK_SPEED_ACTIVE_10)
			link_speed_act_str = "10";
		else
			link_speed_act_str = "??";

		if (p_physp->ext_port_info.link_speed_active & FDR10)
			link_speed_act_str = "FDR10";

		if (p_default_physp->port_info.capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) {
			link_speed_act =
			    ib_port_info_get_link_speed_ext_active(&p_physp->port_info);
			if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_14)
				link_speed_act_str = "14";
			else if (link_speed_act == IB_LINK_SPEED_EXT_ACTIVE_25)
				link_speed_act_str = "25";
			else if (link_speed_act != IB_LINK_SPEED_EXT_ACTIVE_NONE)
				link_speed_act_str = "??";
		}

		fprintf(file, "PHY=%s LOG=%s SPD=%s\n",
			p_physp->port_info.link_width_active == 1 ? "1x" :
			p_physp->port_info.link_width_active == 2 ? "4x" :
			p_physp->port_info.link_width_active == 4 ? "8x" :
			p_physp->port_info.link_width_active == 8 ? "12x" :
			"??",
			port_state == IB_LINK_ACTIVE ? "ACT" :
			port_state == IB_LINK_ARMED ? "ARM" :
			port_state == IB_LINK_INIT ? "INI" : "DWN",
			link_speed_act_str);
	}
}
コード例 #21
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);
}
コード例 #22
0
void osm_smir_rcv_process(IN void *ctx, IN void *data)
{
	osm_sa_t *sa = ctx;
	osm_madw_t *p_madw = data;
	const ib_sa_mad_t *sad_mad;
	const ib_sminfo_record_t *p_rcvd_rec;
	const osm_port_t *p_port = NULL;
	const ib_sm_info_t *p_smi;
	cl_qlist_t rec_list;
	osm_smir_search_ctxt_t context;
	ib_api_status_t status = IB_SUCCESS;
	ib_net64_t comp_mask;
	ib_net64_t port_guid;
	osm_physp_t *p_req_physp;
	osm_port_t *local_port;
	osm_remote_sm_t *p_rem_sm;
	cl_qmap_t *p_sm_guid_tbl;
	uint8_t pri_state;

	CL_ASSERT(sa);

	OSM_LOG_ENTER(sa->p_log);

	CL_ASSERT(p_madw);

	sad_mad = osm_madw_get_sa_mad_ptr(p_madw);
	p_rcvd_rec = (ib_sminfo_record_t *) ib_sa_mad_get_payload_ptr(sad_mad);
	comp_mask = sad_mad->comp_mask;

	CL_ASSERT(sad_mad->attr_id == IB_MAD_ATTR_SMINFO_RECORD);

	/* we only support SubnAdmGet and SubnAdmGetTable methods */
	if (sad_mad->method != IB_MAD_METHOD_GET &&
	    sad_mad->method != IB_MAD_METHOD_GETTABLE) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2804: "
			"Unsupported Method (%s)\n",
			ib_get_sa_method_str(sad_mad->method));
		osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR);
		goto Exit;
	}

	/* update the requester physical port */
	p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn,
						osm_madw_get_mad_addr_ptr
						(p_madw));
	if (p_req_physp == NULL) {
		OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2803: "
			"Cannot find requester physical port\n");
		goto Exit;
	}

	if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) {
		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"Requester port GUID 0x%" PRIx64 "\n",
			cl_ntoh64(osm_physp_get_port_guid(p_req_physp)));
		osm_dump_sm_info_record_v2(sa->p_log, p_rcvd_rec, FILE_ID, OSM_LOG_DEBUG);
	}

	p_smi = &p_rcvd_rec->sm_info;

	cl_qlist_init(&rec_list);

	context.p_rcvd_rec = p_rcvd_rec;
	context.p_list = &rec_list;
	context.comp_mask = sad_mad->comp_mask;
	context.sa = sa;
	context.p_req_physp = p_req_physp;

	cl_plock_acquire(sa->p_lock);

	/*
	   If the user specified a LID, it obviously narrows our
	   work load, since we don't have to search every port
	 */
	if (comp_mask & IB_SMIR_COMPMASK_LID) {
		p_port = osm_get_port_by_lid(sa->p_subn, p_rcvd_rec->lid);
		if (!p_port) {
			status = IB_NOT_FOUND;
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2806: "
				"No port found with LID %u\n",
				cl_ntoh16(p_rcvd_rec->lid));
		}
	}

	if (status == IB_SUCCESS) {
		/* Handle our own SM first */
		local_port = osm_get_port_by_guid(sa->p_subn,
						  sa->p_subn->sm_port_guid);
		if (!local_port) {
			cl_plock_release(sa->p_lock);
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2809: "
				"No port found with GUID 0x%016" PRIx64 "\n",
				cl_ntoh64(sa->p_subn->sm_port_guid));
			goto Exit;
		}

		if (!p_port || local_port == p_port) {
			if (FALSE ==
			    osm_physp_share_pkey(sa->p_log, p_req_physp,
						 local_port->p_physp,
						 sa->p_subn->opt.allow_both_pkeys)) {
				cl_plock_release(sa->p_lock);
				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 2805: "
					"Cannot get SMInfo record due to pkey violation\n");
				goto Exit;
			}

			/* Check that other search components specified match */
			if ((comp_mask & IB_SMIR_COMPMASK_GUID) &&
			    sa->p_subn->sm_port_guid != p_smi->guid)
				goto Remotes;
			if ((comp_mask & IB_SMIR_COMPMASK_PRIORITY) &&
			    sa->p_subn->opt.sm_priority !=
			    ib_sminfo_get_priority(p_smi))
				goto Remotes;
			if ((comp_mask & IB_SMIR_COMPMASK_SMSTATE) &&
			    sa->p_subn->sm_state != ib_sminfo_get_state(p_smi))
				goto Remotes;

			/* Now, add local SMInfo to list */
			pri_state = sa->p_subn->sm_state & 0x0F;
			pri_state |= (sa->p_subn->opt.sm_priority & 0x0F) << 4;
			smir_rcv_new_smir(sa, local_port, context.p_list,
					  sa->p_subn->sm_port_guid,
					  cl_ntoh32(sa->p_subn->p_osm->stats.
						    qp0_mads_sent), pri_state,
					  p_req_physp);
		}

	      Remotes:
		if (p_port && p_port != local_port) {
			/* Find remote SM corresponding to p_port */
			port_guid = osm_port_get_guid(p_port);
			p_sm_guid_tbl = &sa->p_subn->sm_guid_tbl;
			p_rem_sm =
			    (osm_remote_sm_t *) cl_qmap_get(p_sm_guid_tbl,
							    port_guid);
			if (p_rem_sm !=
			    (osm_remote_sm_t *) cl_qmap_end(p_sm_guid_tbl))
				sa_smir_by_comp_mask(sa, p_rem_sm, &context);
			else
				OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 280A: "
					"No remote SM for GUID 0x%016" PRIx64
					"\n", cl_ntoh64(port_guid));
		} else {
			/* Go over all other known (remote) SMs */
			cl_qmap_apply_func(&sa->p_subn->sm_guid_tbl,
					   sa_smir_by_comp_mask_cb, &context);
		}
	}

	cl_plock_release(sa->p_lock);

	osm_sa_respond(sa, p_madw, sizeof(ib_sminfo_record_t), &rec_list);

Exit:
	OSM_LOG_EXIT(sa->p_log);
}
コード例 #23
0
void osm_pi_rcv_process(IN void *context, IN void *data)
{
	osm_sm_t *sm = context;
	osm_madw_t *p_madw = data;
	ib_port_info_t *p_pi;
	ib_smp_t *p_smp;
	osm_port_t *p_port;
	osm_physp_t *p_physp;
	osm_dr_path_t *p_dr_path;
	osm_node_t *p_node;
	osm_pi_context_t *p_context;
	ib_net64_t port_guid, node_guid;
	uint8_t port_num;

	CL_ASSERT(sm);

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_madw);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_context = osm_madw_get_pi_context_ptr(p_madw);
	p_pi = ib_smp_get_payload_ptr(p_smp);

	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);

	/*
	 * Attribute modifier has already been validated upon MAD receive,
	 * which means that port_num has to be valid - it originated from
	 * the request attribute modifier.
	 */
	port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);

	port_guid = p_context->port_guid;
	node_guid = p_context->node_guid;

	osm_dump_port_info_v2(sm->p_log, node_guid, port_guid, port_num, p_pi,
			      FILE_ID, OSM_LOG_DEBUG);

	/* On receipt of client reregister, clear the reregister bit so
	   reregistering won't be sent again and again */
	if (p_context->set_method &&
	    (ib_port_info_get_client_rereg(p_pi) || p_context->client_rereg)) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Client reregister received on response\n");
		ib_port_info_set_client_rereg(p_pi, 0);
		p_context->client_rereg = FALSE;
	}

	/*
	   we might get a response during a light sweep looking for a change in
	   the status of a remote port that did not respond in earlier sweeps.
	   So if the context of the Get was light_sweep - we do not need to
	   do anything with the response - just flag that we need a heavy sweep
	 */
	if (p_context->light_sweep == TRUE) {
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Got light sweep response from remote port of parent node "
			"GUID 0x%" PRIx64 " port 0x%016" PRIx64
			", Commencing heavy sweep\n",
			cl_ntoh64(node_guid), cl_ntoh64(port_guid));
		sm->p_subn->force_heavy_sweep = TRUE;
		sm->p_subn->ignore_existing_lfts = TRUE;
		goto Exit;
	}

	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
	if (PF(!p_port)) {
		CL_PLOCK_RELEASE(sm->p_lock);
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
			"No port object for port with GUID 0x%" PRIx64
			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
			", TID 0x%" PRIx64 "\n",
			cl_ntoh64(port_guid),
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
		goto Exit;
	}

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

	if (PF(p_pi->local_port_num > p_node->node_info.num_ports)) {
		CL_PLOCK_RELEASE(sm->p_lock);
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F15: "
			"Received PortInfo for port GUID 0x%" PRIx64 " is "
			"non-compliant and is being ignored since the "
			"local port num %u > num ports %u\n",
			cl_ntoh64(port_guid), p_pi->local_port_num,
			p_node->node_info.num_ports);
		goto Exit;
	}

	/*
	   If we were setting the PortInfo, then receiving
	   this attribute was not part of sweeping the subnet.
	   In this case, just update the PortInfo attribute.

	   In an unfortunate blunder, the IB spec defines the
	   return method for Set() as a GetResp().  Thus, we can't
	   use the method (what would have been SetResp()) to determine
	   our course of action.  So, we have to carry this extra
	   boolean around to determine if we were doing Get() or Set().
	 */
	if (p_context->set_method)
		pi_rcv_process_set(sm, p_node, port_num, p_madw);
	else {

		/*
		   This PortInfo arrived because we did a Get() method,
		   most likely due to a subnet sweep in progress.
		 */
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Discovered port num %u with GUID 0x%" PRIx64
			" for parent node GUID 0x%" PRIx64
			", TID 0x%" PRIx64 "\n",
			port_num, cl_ntoh64(port_guid),
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));

		p_physp = osm_node_get_physp_ptr(p_node, port_num);

		CL_ASSERT(p_physp);

		/* Update the directed route path to this port
		   in case the old path is no longer usable. */
		p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
		osm_dr_path_init(p_dr_path, p_smp->hop_count,
				 p_smp->initial_path);

		p_physp->need_update = osm_pi_rcv_update_self(sm, p_physp, p_pi);

		switch (osm_node_get_type(p_node)) {
		case IB_NODE_TYPE_CA:
		case IB_NODE_TYPE_ROUTER:
			if (!p_node->physp_discovered[port_num]) {
				p_port->discovery_count++;
				p_node->physp_discovered[port_num] = 1;
			}
			p_physp->need_update = osm_pi_rcv_update_neighbor(p_physp);
			pi_rcv_process_ca_or_router_port(sm, p_node, p_physp,
							 p_pi);
			break;
		case IB_NODE_TYPE_SWITCH:
			if (!p_node->physp_discovered[port_num]) {
				p_port->discovery_count++;
				p_node->physp_discovered[port_num] = 1;
			}
			if (port_num == 0)
				pi_rcv_process_switch_port0(sm, p_node,
							    p_physp, p_pi);
			else
				pi_rcv_process_switch_ext_port(sm, p_node,
							       p_physp, p_pi);
			break;
		default:
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
				"Unknown node type %u with GUID 0x%" PRIx64
				"\n", osm_node_get_type(p_node),
				cl_ntoh64(node_guid));
			break;
		}

		/*
		   Get the tables on the physp.
		 */
		if (p_physp->need_update || (p_node->sw &&
					     p_node->sw->need_update))
			pi_rcv_get_pkey_slvl_vla_tables(sm, p_node, p_physp);

	}

	CL_PLOCK_RELEASE(sm->p_lock);

Exit:
	/*
	   Release the lock before jumping here!!
	 */
	OSM_LOG_EXIT(sm->p_log);
}
コード例 #24
0
void osm_pi_rcv_process(IN void *context, IN void *data)
{
	osm_sm_t *sm = context;
	osm_madw_t *p_madw = data;
	ib_port_info_t *p_pi;
	ib_smp_t *p_smp;
	osm_port_t *p_port;
	osm_physp_t *p_physp;
	osm_dr_path_t *p_dr_path;
	osm_node_t *p_node;
	osm_pi_context_t *p_context;
	ib_net64_t port_guid;
	ib_net64_t node_guid;
	uint8_t port_num;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(sm);
	CL_ASSERT(p_madw);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_context = osm_madw_get_pi_context_ptr(p_madw);
	p_pi = (ib_port_info_t *) ib_smp_get_payload_ptr(p_smp);

	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_PORT_INFO);

	port_num = (uint8_t) cl_ntoh32(p_smp->attr_mod);

	port_guid = p_context->port_guid;
	node_guid = p_context->node_guid;

	osm_dump_port_info(sm->p_log,
			   node_guid, port_guid, port_num, p_pi, OSM_LOG_DEBUG);

	/* On receipt of client reregister, clear the reregister bit so
	   reregistering won't be sent again and again */
	if (ib_port_info_get_client_rereg(p_pi)) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"Client reregister received on response\n");
		ib_port_info_set_client_rereg(p_pi, 0);
	}

	/*
	   we might get a response during a light sweep looking for a change in
	   the status of a remote port that did not respond in earlier sweeps.
	   So if the context of the Get was light_sweep - we do not need to
	   do anything with the response - just flag that we need a heavy sweep
	 */
	if (p_context->light_sweep == TRUE) {
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Got light sweep response from remote port of parent node "
			"GUID 0x%" PRIx64 " port 0x%016" PRIx64
			", Commencing heavy sweep\n",
			cl_ntoh64(node_guid), cl_ntoh64(port_guid));
		sm->p_subn->force_heavy_sweep = TRUE;
		sm->p_subn->ignore_existing_lfts = TRUE;
		goto Exit;
	}

	CL_PLOCK_EXCL_ACQUIRE(sm->p_lock);
	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
	if (!p_port) {
		CL_PLOCK_RELEASE(sm->p_lock);
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F06: "
			"No port object for port with GUID 0x%" PRIx64
			"\n\t\t\t\tfor parent node GUID 0x%" PRIx64
			", TID 0x%" PRIx64 "\n",
			cl_ntoh64(port_guid),
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));
		goto Exit;
	}

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

	/*
	   If we were setting the PortInfo, then receiving
	   this attribute was not part of sweeping the subnet.
	   In this case, just update the PortInfo attribute.

	   In an unfortunate blunder, the IB spec defines the
	   return method for Set() as a GetResp().  Thus, we can't
	   use the method (what would have been SetResp()) to determine
	   our course of action.  So, we have to carry this extra
	   boolean around to determine if we were doing Get() or Set().
	 */
	if (p_context->set_method)
		osm_pi_rcv_process_set(sm, p_node, port_num, p_madw);
	else {
		p_port->discovery_count++;

		/*
		   This PortInfo arrived because we did a Get() method,
		   most likely due to a subnet sweep in progress.
		 */
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Discovered port num %u with GUID 0x%" PRIx64
			" for parent node GUID 0x%" PRIx64
			", TID 0x%" PRIx64 "\n",
			port_num, cl_ntoh64(port_guid),
			cl_ntoh64(node_guid), cl_ntoh64(p_smp->trans_id));

		p_physp = osm_node_get_physp_ptr(p_node, port_num);

		/*
		   Determine if we encountered a new Physical Port.
		   If so, initialize the new Physical Port then
		   continue processing as normal.
		 */
		if (!p_physp) {
			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
				"Initializing port number %u\n", port_num);
			p_physp = &p_node->physp_table[port_num];
			osm_physp_init(p_physp,
				       port_guid,
				       port_num,
				       p_node,
				       osm_madw_get_bind_handle(p_madw),
				       p_smp->hop_count, p_smp->initial_path);
		} else {
			/*
			   Update the directed route path to this port
			   in case the old path is no longer usable.
			 */
			p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
			osm_dr_path_init(p_dr_path,
					 osm_madw_get_bind_handle(p_madw),
					 p_smp->hop_count, p_smp->initial_path);
		}

		/* if port just inited or reached INIT state (external reset)
		   request update for port related tables */
		p_physp->need_update =
		    (ib_port_info_get_port_state(p_pi) == IB_LINK_INIT ||
		     p_physp->need_update > 1) ? 1 : 0;

		switch (osm_node_get_type(p_node)) {
		case IB_NODE_TYPE_CA:
		case IB_NODE_TYPE_ROUTER:
			__osm_pi_rcv_process_ca_or_router_port(sm,
							       p_node, p_physp,
							       p_pi);
			break;
		case IB_NODE_TYPE_SWITCH:
			__osm_pi_rcv_process_switch_port(sm,
							 p_node, p_physp, p_pi);
			break;
		default:
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F07: "
				"Unknown node type %u with GUID 0x%" PRIx64
				"\n", osm_node_get_type(p_node),
				cl_ntoh64(node_guid));
			break;
		}

		/*
		   Get the tables on the physp.
		 */
		if (p_physp->need_update || sm->p_subn->need_update)
			__osm_pi_rcv_get_pkey_slvl_vla_tables(sm, p_node,
							      p_physp);

	}

	CL_PLOCK_RELEASE(sm->p_lock);

Exit:
	/*
	   Release the lock before jumping here!!
	 */
	OSM_LOG_EXIT(sm->p_log);
}
コード例 #25
0
ファイル: osm_sa.c プロジェクト: Cai900205/test
int osm_sa_db_file_load(osm_opensm_t * p_osm)
{
	char line[1024];
	char *file_name;
	FILE *file;
	int ret = 0;
	osm_mgrp_t *p_mgrp = NULL;
	unsigned rereg_clients = 0;
	unsigned lineno;

	if (!p_osm->subn.first_time_master_sweep) {
		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
			"Not first sweep - skip SA DB restore\n");
		return 0;
	}

	file_name = p_osm->subn.opt.sa_db_file;
	if (!file_name) {
		OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
			"sa db file name is not specifed. Skip restore\n");
		return 0;
	}

	file = fopen(file_name, "r");
	if (!file) {
		OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: "
			"Can't open sa db file \'%s\'. Skip restoring\n",
			file_name);
		return -1;
	}

	OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE,
		"Restoring SA DB from file \'%s\'\n",
		file_name);

	lineno = 0;

	while (fgets(line, sizeof(line) - 1, file) != NULL) {
		char *p;
		uint8_t val;

		lineno++;

		p = line;
		while (isspace(*p))
			p++;

		if (*p == '#')
			continue;

		if (!strncmp(p, "MC Group", 8)) {
			ib_member_rec_t mcm_rec;
			ib_net16_t mlid;
			unsigned well_known = 0;

			p_mgrp = NULL;
			memset(&mcm_rec, 0, sizeof(mcm_rec));

			PARSE_AHEAD(p, net16, " 0x", &mlid);
			if (strstr(p, "well known"))
				well_known = 1;
			PARSE_AHEAD(p, net64, " mgid=0x",
				    &mcm_rec.mgid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &mcm_rec.mgid.unicast.interface_id);
			PARSE_AHEAD(p, net64, " port_gid=0x",
				    &mcm_rec.port_gid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &mcm_rec.port_gid.unicast.interface_id);
			PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey);
			PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid);
			PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu);
			PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass);
			PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey);
			PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate);
			PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life);
			PARSE_AHEAD(p, net32, " sl_flow_hop=0x",
				    &mcm_rec.sl_flow_hop);
			PARSE_AHEAD(p, net8, " scope_state=0x",
				    &mcm_rec.scope_state);
			PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
			mcm_rec.proxy_join = val;

			p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec,
					      well_known);
			if (!p_mgrp)
				rereg_clients = 1;
			if (cl_ntoh16(mlid) > p_osm->sm.mlids_init_max)
				p_osm->sm.mlids_init_max = cl_ntoh16(mlid);
		} else if (p_mgrp && !strncmp(p, "mcm_port", 8)) {
			ib_member_rec_t mcmr;
			ib_net64_t guid;
			osm_port_t *port;
			boolean_t proxy;

			PARSE_AHEAD(p, net64, " port_gid=0x",
				    &mcmr.port_gid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &mcmr.port_gid.unicast.interface_id);
			PARSE_AHEAD(p, net8, " scope_state=0x", &mcmr.scope_state);
			PARSE_AHEAD(p, net8, " proxy_join=0x", &val);
			proxy = val;

			guid = mcmr.port_gid.unicast.interface_id;
			port = osm_get_port_by_guid(&p_osm->subn, guid);
			if (port &&
			    cl_qmap_get(&p_mgrp->mcm_port_tbl, guid) ==
			    cl_qmap_end(&p_mgrp->mcm_port_tbl) &&
			    !osm_mgrp_add_port(&p_osm->subn, &p_osm->log,
						p_mgrp, port, &mcmr, proxy))
				rereg_clients = 1;
		} else if (!strncmp(p, "Service Record:", 15)) {
			ib_service_record_t s_rec;
			uint32_t modified_time, lease_period;

			p_mgrp = NULL;
			memset(&s_rec, 0, sizeof(s_rec));

			PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id);
			PARSE_AHEAD(p, net64, " gid=0x",
				    &s_rec.service_gid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &s_rec.service_gid.unicast.interface_id);
			PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey);
			PARSE_AHEAD(p, net32, " lease=0x",
				    &s_rec.service_lease);
			PARSE_AHEAD(p, net64, " key=0x",
				    (ib_net64_t *) (&s_rec.service_key[0]));
			PARSE_AHEAD(p, net64, ":0x",
				    (ib_net64_t *) (&s_rec.service_key[8]));
			PARSE_AHEAD(p, string64, " name=", s_rec.service_name);
			PARSE_AHEAD(p, net64, " data8=0x",
				    (ib_net64_t *) (&s_rec.service_data8[0]));
			PARSE_AHEAD(p, net64, ":0x",
				    (ib_net64_t *) (&s_rec.service_data8[8]));
			PARSE_AHEAD(p, net64, " data16=0x",
				    (ib_net64_t *) (&s_rec.service_data16[0]));
			PARSE_AHEAD(p, net64, ":0x",
				    (ib_net64_t *) (&s_rec.service_data16[4]));
			PARSE_AHEAD(p, net64, " data32=0x",
				    (ib_net64_t *) (&s_rec.service_data32[0]));
			PARSE_AHEAD(p, net64, ":0x",
				    (ib_net64_t *) (&s_rec.service_data32[2]));
			PARSE_AHEAD(p, net64, " data64=0x",
				    &s_rec.service_data64[0]);
			PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]);
			PARSE_AHEAD(p, net32, " modified_time=0x",
				    &modified_time);
			PARSE_AHEAD(p, net32, " lease_period=0x",
				    &lease_period);

			if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time),
				      cl_ntoh32(lease_period)))
				rereg_clients = 1;
		} else if (!strncmp(p, "InformInfo Record:", 18)) {
			ib_inform_info_record_t i_rec;
			osm_mad_addr_t rep_addr;
			ib_net16_t val16;

			p_mgrp = NULL;
			memset(&i_rec, 0, sizeof(i_rec));
			memset(&rep_addr, 0, sizeof(rep_addr));

			PARSE_AHEAD(p, net64, " subscriber_gid=0x",
				    &i_rec.subscriber_gid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &i_rec.subscriber_gid.unicast.interface_id);
			PARSE_AHEAD(p, net16, " subscriber_enum=0x",
				    &i_rec.subscriber_enum);
			PARSE_AHEAD(p, net64, " gid=0x",
				    &i_rec.inform_info.gid.unicast.prefix);
			PARSE_AHEAD(p, net64, ":0x",
				    &i_rec.inform_info.gid.unicast.
				    interface_id);
			PARSE_AHEAD(p, net16, " lid_range_begin=0x",
				    &i_rec.inform_info.lid_range_begin);
			PARSE_AHEAD(p, net16, " lid_range_end=0x",
				    &i_rec.inform_info.lid_range_end);
			PARSE_AHEAD(p, net8, " is_generic=0x",
				    &i_rec.inform_info.is_generic);
			PARSE_AHEAD(p, net8, " subscribe=0x",
				    &i_rec.inform_info.subscribe);
			PARSE_AHEAD(p, net16, " trap_type=0x",
				    &i_rec.inform_info.trap_type);
			PARSE_AHEAD(p, net16, " trap_num=0x",
				    &i_rec.inform_info.g_or_v.generic.trap_num);
			PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x",
				    &i_rec.inform_info.g_or_v.generic.
				    qpn_resp_time_val);
			PARSE_AHEAD(p, net32, " node_type=0x",
				    (uint32_t *) & i_rec.inform_info.g_or_v.
				    generic.reserved2);

			PARSE_AHEAD(p, net16, " rep_addr: lid=0x",
				    &rep_addr.dest_lid);
			PARSE_AHEAD(p, net8, " path_bits=0x",
				    &rep_addr.path_bits);
			PARSE_AHEAD(p, net8, " static_rate=0x",
				    &rep_addr.static_rate);
			PARSE_AHEAD(p, net32, " remote_qp=0x",
				    &rep_addr.addr_type.gsi.remote_qp);
			PARSE_AHEAD(p, net32, " remote_qkey=0x",
				    &rep_addr.addr_type.gsi.remote_qkey);
			PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16);
			rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16);
			PARSE_AHEAD(p, net8, " sl=0x",
				    &rep_addr.addr_type.gsi.service_level);

			if (load_infr(p_osm, &i_rec, &rep_addr))
				rereg_clients = 1;
		}
	}

	/*
	 * If loading succeeded, do whatever 'no_clients_rereg' says.
	 * If loading failed at some point, turn off the 'no_clients_rereg'
	 * option (turn on re-registration requests).
	 */
	if (rereg_clients)
		p_osm->subn.opt.no_clients_rereg = FALSE;

	/* We've just finished loading SA DB file - clear the "dirty" flag */
	p_osm->sa.dirty = FALSE;

_error:
	fclose(file);
	return ret;
}
コード例 #26
0
static void
__osmv_dispatch_rmpp_snd(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)
{
	osmv_rmpp_send_ctx_t *p_send_ctx = osmv_txn_get_rmpp_send_ctx(p_txn);

	uint32_t old_wl = p_send_ctx->window_last;
	uint32_t total_segs = osmv_rmpp_send_ctx_get_num_segs(p_send_ctx);
	uint32_t seg_num = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->seg_num);
	uint32_t new_wl = cl_ntoh32(((ib_rmpp_mad_t *) p_mad)->paylen_newwin);
	osmv_bind_obj_t *p_bo = (osmv_bind_obj_t *) h_bind;

	OSM_LOG_ENTER(p_bo->p_vendor->p_log);

	if (TRUE == osmv_rmpp_is_abort_stop(p_mad)) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6502: "
			"The remote side sent an ABORT/STOP indication.\n");
		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	if (FALSE == osmv_rmpp_is_ack(p_mad)) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"Not supposed to receive DATA packets --> dropping the MAD\n");
		goto dispatch_rmpp_snd_done;
	}

	/* Continue processing the ACK */
	if (seg_num > old_wl) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6503: "
			"ACK received for a non-sent segment %d\n", seg_num);

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

		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"__osmv_dispatch_rmpp_snd: "
		"New WL = %u Old WL = %u Total Segs = %u\n",
		new_wl, old_wl, total_segs);

	if (new_wl < old_wl) {
		osm_log(p_bo->p_vendor->p_log, OSM_LOG_ERROR,
			"__osmv_dispatch_rmpp_snd: ERR 6508: "
			"The receiver requests a smaller WL (%d) than before (%d)\n",
			new_wl, old_wl);

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

		osmv_rmpp_snd_error(p_send_ctx, IB_REMOTE_ERROR);
		goto dispatch_rmpp_snd_done;
	}

	/* Update the sender's window, and optionally wake up the sender thread
	 * Note! A single ACK can acknowledge a whole range of segments: [WF..SEG_NUM]
	 */
	osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
		"ACK for seg_num #%d accepted.\n", seg_num);

	if (seg_num == old_wl) {

		osm_log(p_bo->p_vendor->p_log, OSM_LOG_DEBUG,
			"The send window [%d:%d] is totally acknowledged.\n",
			p_send_ctx->window_first, old_wl);

		p_send_ctx->window_first = seg_num + 1;
		p_send_ctx->window_last =
		    (new_wl < total_segs) ? new_wl : total_segs;

		/* Remove the response timeout event for the window */
		osmv_txn_remove_timeout_ev(h_bind, osmv_txn_get_key(p_txn));

		/* Wake up the sending thread */
		cl_event_signal(&p_send_ctx->event);
	}

dispatch_rmpp_snd_done:
	OSM_LOG_EXIT(p_bo->p_vendor->p_log);
}