예제 #1
0
static void ni_rcv_get_port_info(IN osm_sm_t * sm, IN osm_node_t * node,
				 IN const osm_madw_t * madw)
{
	osm_madw_context_t context;
	osm_physp_t *physp;
	ib_node_info_t *ni;
	unsigned port;
	ib_api_status_t status;
	int mlnx_epi_supported = 0;

	ni = ib_smp_get_payload_ptr(osm_madw_get_smp_ptr(madw));

	port = ib_node_info_get_local_port_num(ni);

	if (sm->p_subn->opt.fdr10)
		mlnx_epi_supported = is_mlnx_ext_port_info_supported(ni->device_id);

	physp = osm_node_get_physp_ptr(node, port);
	if (!physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1E: "
			"Failed to find physp for port %d of Node GUID 0x%"
			PRIx64 "\n", port,
			cl_ntoh64(osm_node_get_node_guid(node)));
		return;
	}

	context.pi_context.node_guid = osm_node_get_node_guid(node);
	context.pi_context.port_guid = osm_physp_get_port_guid(physp);
	context.pi_context.set_method = FALSE;
	context.pi_context.light_sweep = FALSE;
	context.pi_context.active_transition = FALSE;
	context.pi_context.client_rereg = FALSE;

	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(physp),
			     IB_MAD_ATTR_PORT_INFO, cl_hton32(port),
			     TRUE, 0, CL_DISP_MSGID_NONE, &context);
	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD02: "
			"Failure initiating PortInfo request (%s)\n",
			ib_get_err_str(status));
	if (mlnx_epi_supported) {
		status = osm_req_get(sm,
				     osm_physp_get_dr_path_ptr(physp),
				     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
				     cl_hton32(port),
				     TRUE, 0, CL_DISP_MSGID_NONE, &context);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0B: "
				"Failure initiating MLNX ExtPortInfo request (%s)\n",
				ib_get_err_str(status));
	}
}
예제 #2
0
bool IBConnection::_writeKeys( const struct IBDest *myDest )
{
    char msg[KEY_MSG_SIZE];

    sprintf( msg,
             KEY_PRINT_FMT,
             cl_hton16(myDest->lid),
             cl_hton32(myDest->qpn),
             cl_hton32(myDest->psn),
             cl_hton32(myDest->rkey),
             myDest->vaddr);

    _socketConnection->send( msg, KEY_MSG_SIZE );
    return true;
}
예제 #3
0
파일: ibsendtrap.c 프로젝트: Cai900205/test
static void build_trap144_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
	n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
	n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
	n->g_or_v.generic.trap_num = cl_hton16(144);
	n->issuer_lid = cl_hton16((uint16_t) port->lid);
	n->data_details.ntc_144.lid = n->issuer_lid;
	n->data_details.ntc_144.new_cap_mask = cl_hton32(get_cap_mask(port));
	n->data_details.ntc_144.local_changes =
	    TRAP_144_MASK_OTHER_LOCAL_CHANGES;
}
예제 #4
0
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void pi_rcv_process_switch_port0(IN osm_sm_t * sm,
					IN osm_node_t * p_node,
					IN osm_physp_t * p_physp,
					IN ib_port_info_t * p_pi)
{
	ib_api_status_t status;
	osm_madw_context_t context;
	uint8_t port, num_ports;

	OSM_LOG_ENTER(sm->p_log);

	if (p_physp->need_update)
		sm->p_subn->ignore_existing_lfts = TRUE;

	pi_rcv_check_and_fix_lid(sm->p_log, p_pi, p_physp);

	/* Update the PortInfo attribute */
	osm_physp_set_port_info(p_physp, p_pi, sm);

	/* Determine if base switch port 0 */
	if (p_node->sw &&
	    !ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info))
		/* PortState is not used on BSP0 but just in case it is DOWN */
		p_physp->port_info = *p_pi;

	/* Now, query PortInfo for the switch external ports */
	num_ports = osm_node_get_num_physp(p_node);

	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
	context.pi_context.set_method = FALSE;
	context.pi_context.light_sweep = FALSE;
	context.pi_context.active_transition = FALSE;
	context.pi_context.client_rereg = FALSE;

	for (port = 1; port < num_ports; port++) {
		status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
				     IB_MAD_ATTR_PORT_INFO, cl_hton32(port),
				     FALSE,
				     ib_port_info_get_m_key(&p_physp->port_info),
				     CL_DISP_MSGID_NONE, &context);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F16: "
				"Failure initiating PortInfo request (%s)\n",
				ib_get_err_str(status));
	}

	pi_rcv_process_endport(sm, p_physp, p_pi);
	OSM_LOG_EXIT(sm->p_log);
}
예제 #5
0
static int set_lft_block(IN osm_switch_t *p_sw, IN osm_ucast_mgr_t *p_mgr,
			 IN uint16_t block_id_ho)
{
	uint8_t block[IB_SMP_DATA_SIZE];
	osm_madw_context_t context;
	osm_dr_path_t *p_path;
	ib_api_status_t status;

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

	p_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_sw->p_node, 0));

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

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

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

	status = osm_req_set(p_mgr->sm, p_path,
			     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
			     IB_SMP_DATA_SIZE, IB_MAD_ATTR_LIN_FWD_TBL,
			     cl_hton32(block_id_ho),
			     CL_DISP_MSGID_NONE, &context);
	if (status != IB_SUCCESS) {
		OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR, "ERR 3A05: "
			"Sending linear fwd. tbl. block failed (%s)\n",
			ib_get_err_str(status));
		return -1;
	}

	return 0;
}
예제 #6
0
static qos_mad_item_t *osm_qos_mad_create(IN osm_sm_t * sm,
					  IN osm_physp_t * p,
					  IN uint32_t data_size,
					  IN uint8_t * p_data,
					  IN ib_net16_t attr_id,
					  IN uint32_t attr_mod)

{
	qos_mad_item_t *p_mad;
	osm_madw_context_t context;
	osm_madw_t *p_madw;
	osm_node_t *p_node;

	p_node = osm_physp_get_node_ptr(p);

	switch (attr_id){
	case IB_MAD_ATTR_SLVL_TABLE:
		context.slvl_context.node_guid = osm_node_get_node_guid(p_node);
		context.slvl_context.port_guid = osm_physp_get_port_guid(p);
		context.slvl_context.set_method = TRUE;
		break;
	case IB_MAD_ATTR_VL_ARBITRATION:
		context.vla_context.node_guid = osm_node_get_node_guid(p_node);
		context.vla_context.port_guid = osm_physp_get_port_guid(p);
		context.vla_context.set_method = TRUE;
		break;
	default:
		return NULL;
	}

	p_mad = (qos_mad_item_t *) malloc(sizeof(*p_mad));
	if (!p_mad)
		return NULL;

	memset(p_mad, 0, sizeof(*p_mad));

	p_madw = osm_prepare_req_set(sm, osm_physp_get_dr_path_ptr(p),
				     p_data, data_size,
				     attr_id, cl_hton32(attr_mod),
				     CL_DISP_MSGID_NONE, &context);

	if (p_madw == NULL) {
		free(p_mad);
		return NULL;
	}
	p_mad->p_madw = p_madw;
	return p_mad;
}
예제 #7
0
static void mpr_rcv_build_pr(IN osm_sa_t * sa,
			     IN const osm_alias_guid_t * p_src_alias_guid,
			     IN const osm_alias_guid_t * p_dest_alias_guid,
			     IN uint16_t src_lid_ho, IN uint16_t dest_lid_ho,
			     IN uint8_t preference,
			     IN const osm_path_parms_t * p_parms,
			     OUT ib_path_rec_t * p_pr)
{
	const osm_physp_t *p_src_physp, *p_dest_physp;

	OSM_LOG_ENTER(sa->p_log);

	p_src_physp = p_src_alias_guid->p_base_port->p_physp;
	p_dest_physp = p_dest_alias_guid->p_base_port->p_physp;

	p_pr->dgid.unicast.prefix = osm_physp_get_subnet_prefix(p_dest_physp);
	p_pr->dgid.unicast.interface_id = osm_physp_get_port_guid(p_dest_physp);

	p_pr->sgid.unicast.prefix = osm_physp_get_subnet_prefix(p_src_physp);
	p_pr->sgid.unicast.interface_id = osm_physp_get_port_guid(p_src_physp);

	p_pr->dlid = cl_hton16(dest_lid_ho);
	p_pr->slid = cl_hton16(src_lid_ho);

	p_pr->hop_flow_raw &= cl_hton32(1 << 31);

	p_pr->pkey = p_parms->pkey;
	ib_path_rec_set_qos_class(p_pr, 0);
	ib_path_rec_set_sl(p_pr, p_parms->sl);
	p_pr->mtu = (uint8_t) (p_parms->mtu | 0x80);
	p_pr->rate = (uint8_t) (p_parms->rate | 0x80);

	/* According to 1.2 spec definition 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)
		p_pr->pkt_life = 0x80;	/* loopback */
	else
		p_pr->pkt_life = (uint8_t) (p_parms->pkt_life | 0x80);

	p_pr->preference = preference;

	/* always return num_path = 0 so this is only the reversible component */
	if (p_parms->reversible)
		p_pr->num_path = 0x80;

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

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_sw);

	p_node = p_sw->p_node;

	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);

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

	max_block_id_ho = osm_switch_get_max_block_id_in_use(p_sw);

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

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

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

	OSM_LOG_EXIT(sm->p_log);
}
예제 #9
0
IBInterface::IBInterface( )
    : _completionQueue( 0 )
    , _queuePair( 0 )
    , _posReadInBuffer( 0 )
    , _firstTimeWrite( true )
    , _numBufRead( 0 )
    , _numBufWrite( 0 )
{
    srand(1);
    _countWrite = 0;
    _psn = cl_hton32( rand() & 0xffffff );
    _writePoll.resize( EQ_NUMBLOCKMEMORY );
    _readPoll.resize( EQ_NUMBLOCKMEMORY );
    _dests.resize( EQ_NUMBLOCKMEMORY );
    _writeBlocks.resize( EQ_NUMBLOCKMEMORY );
    _readBlocks.resize( EQ_NUMBLOCKMEMORY );
    for (int i = 0; i < EQ_NUMBLOCKMEMORY ; i++)
    {
        _writeBlocks[i] = new IBMemBlock();
        _readBlocks[i] = new IBMemBlock();
    }
    

     memset( _readPoll.getData(), 0, sizeof ( uint32_t ) 
                            * EQ_NUMBLOCKMEMORY );
     memset( _writePoll.getData(), true, sizeof ( bool ) * EQ_NUMBLOCKMEMORY );

    _floatTimeReadNB = 0.0f;
    _floatTimeReadSync  = 0.0f;
    
    _timeTotalWaitPoll = 0.0f;
    _timeTotalWaitobj  = 0.0f;

    _timeTotalWrite  = 0.0f;
    _timeTotalWriteWait  = 0.0f;

    _timeCopyBufferRead = 0.0f;
    _timeCopyBufferWrite = 0.0f;
}
예제 #10
0
static ib_api_status_t sl2vl_update_table(osm_sm_t * sm,
					  osm_physp_t * p, uint8_t in_port,
					  uint8_t out_port,
					  unsigned force_update,
					  const ib_slvl_table_t * sl2vl_table)
{
	osm_madw_context_t context;
	ib_slvl_table_t tbl, *p_tbl;
	osm_node_t *p_node = osm_physp_get_node_ptr(p);
	uint32_t attr_mod;
	unsigned vl_mask;
	uint8_t vl1, vl2;
	int i;

	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;

	for (i = 0; i < IB_MAX_NUM_VLS / 2; i++) {
		vl1 = sl2vl_table->raw_vl_by_sl[i] >> 4;
		vl2 = sl2vl_table->raw_vl_by_sl[i] & 0xf;
		if (vl1 != 15)
			vl1 &= vl_mask;
		if (vl2 != 15)
			vl2 &= vl_mask;
		tbl.raw_vl_by_sl[i] = (vl1 << 4) | vl2;
	}

	if (!force_update && (p_tbl = osm_physp_get_slvl_tbl(p, in_port)) &&
	    !memcmp(p_tbl, &tbl, sizeof(tbl)))
		return IB_SUCCESS;

	context.slvl_context.node_guid = osm_node_get_node_guid(p_node);
	context.slvl_context.port_guid = osm_physp_get_port_guid(p);
	context.slvl_context.set_method = TRUE;
	attr_mod = in_port << 8 | out_port;
	return osm_req_set(sm, osm_physp_get_dr_path_ptr(p),
			   (uint8_t *) & tbl, sizeof(tbl),
			   IB_MAD_ATTR_SLVL_TABLE,
			   cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
}
예제 #11
0
/*
 * QoS primitives
 */
static ib_api_status_t vlarb_update_table_block(osm_sm_t * sm,
						osm_physp_t * p,
						uint8_t port_num,
						unsigned force_update,
						const ib_vl_arb_table_t *
						table_block,
						unsigned block_length,
						unsigned block_num)
{
	ib_vl_arb_table_t block;
	osm_madw_context_t context;
	uint32_t attr_mod;
	unsigned vl_mask, i;

	vl_mask = (1 << (ib_port_info_get_op_vls(&p->port_info) - 1)) - 1;

	memset(&block, 0, sizeof(block));
	memcpy(&block, table_block, block_length * sizeof(block.vl_entry[0]));
	for (i = 0; i < block_length; i++)
		block.vl_entry[i].vl &= vl_mask;

	if (!force_update &&
	    !memcmp(&p->vl_arb[block_num], &block,
		    block_length * sizeof(block.vl_entry[0])))
		return IB_SUCCESS;

	context.vla_context.node_guid =
	    osm_node_get_node_guid(osm_physp_get_node_ptr(p));
	context.vla_context.port_guid = osm_physp_get_port_guid(p);
	context.vla_context.set_method = TRUE;
	attr_mod = ((block_num + 1) << 16) | port_num;

	return osm_req_set(sm, osm_physp_get_dr_path_ptr(p),
			   (uint8_t *) & block, sizeof(block),
			   IB_MAD_ATTR_VL_ARBITRATION,
			   cl_hton32(attr_mod), CL_DISP_MSGID_NONE, &context);
}
예제 #12
0
/**********************************************************************
 * Send SubnSet(SMInfo) SMP with HANDOVER attribute to the
 * remote_sm indicated.
 **********************************************************************/
static void state_mgr_send_handover(IN osm_sm_t * sm, IN osm_remote_sm_t * p_sm)
{
	uint8_t payload[IB_SMP_DATA_SIZE];
	ib_sm_info_t *p_smi = (ib_sm_info_t *) payload;
	osm_madw_context_t context;
	const osm_port_t *p_port;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

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

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

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

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

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

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

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

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
예제 #13
0
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void pi_rcv_process_switch_ext_port(IN osm_sm_t * sm,
					   IN osm_node_t * p_node,
					   IN osm_physp_t * p_physp,
					   IN ib_port_info_t * p_pi)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_madw_context_t context;
	osm_physp_t *p_remote_physp, *physp0;
	osm_node_t *p_remote_node;
	ib_net64_t m_key;
	unsigned data_vls;
	uint8_t port_num;
	uint8_t remote_port_num;
	osm_dr_path_t path;
	int mlnx_epi_supported = 0;

	OSM_LOG_ENTER(sm->p_log);

	/*
	   Check the state of the physical port.
	   If there appears to be something on the other end of the wire,
	   then ask for NodeInfo.  Ignore the switch management port.
	 */
	port_num = osm_physp_get_port_num(p_physp);

	if (sm->p_subn->opt.fdr10)
		mlnx_epi_supported = is_mlnx_ext_port_info_supported(
						ib_node_info_get_vendor_id(&p_node->node_info),
						p_node->node_info.device_id);

	/* if in_sweep_hop_0 is TRUE, then this means the SM is on the switch,
	   and we got switchInfo of our local switch. Do not continue
	   probing through the switch. */
	switch (ib_port_info_get_port_state(p_pi)) {
	case IB_LINK_DOWN:
		p_remote_physp = osm_physp_get_remote(p_physp);
		if (p_remote_physp) {
			p_remote_node =
			    osm_physp_get_node_ptr(p_remote_physp);
			remote_port_num =
			    osm_physp_get_port_num(p_remote_physp);

			OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
				"Unlinking local node 0x%" PRIx64
				", port %u"
				"\n\t\t\t\tand remote node 0x%" PRIx64
				", port %u\n",
				cl_ntoh64(osm_node_get_node_guid
					  (p_node)), port_num,
				cl_ntoh64(osm_node_get_node_guid
					  (p_remote_node)),
				remote_port_num);

			if (sm->ucast_mgr.cache_valid)
				osm_ucast_cache_add_link(&sm->ucast_mgr,
							 p_physp,
							 p_remote_physp);

			osm_node_unlink(p_node, (uint8_t) port_num,
					p_remote_node,
					(uint8_t) remote_port_num);

		}
		break;

	case IB_LINK_INIT:
	case IB_LINK_ARMED:
	case IB_LINK_ACTIVE:
		physp0 = osm_node_get_physp_ptr(p_node, 0);
		if (mlnx_epi_supported) {
			m_key = ib_port_info_get_m_key(&physp0->port_info);

			context.pi_context.node_guid = osm_node_get_node_guid(p_node);
			context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
			context.pi_context.set_method = FALSE;
			context.pi_context.light_sweep = FALSE;
			context.pi_context.active_transition = FALSE;
			context.pi_context.client_rereg = FALSE;
			status = osm_req_get(sm,
					     osm_physp_get_dr_path_ptr(p_physp),
					     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
					     cl_hton32(port_num), FALSE, m_key,
					     CL_DISP_MSGID_NONE, &context);
			if (status != IB_SUCCESS)
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F11: "
					"Failure initiating MLNX ExtPortInfo request (%s)\n",
					ib_get_err_str(status));
		}
		if (sm->p_subn->in_sweep_hop_0 == FALSE) {
			/*
			   To avoid looping forever, only probe the port if it
			   is NOT the port that responded to the SMP.

			   Request node info from the other end of this link:
			   1) Copy the current path from the parent node.
			   2) Extend the path to the next hop thru this port.
			   3) Request node info with the new path

			 */
			if (p_pi->local_port_num !=
			    osm_physp_get_port_num(p_physp)) {
				path = *osm_physp_get_dr_path_ptr(p_physp);

				if (osm_dr_path_extend(&path,
						       osm_physp_get_port_num
						       (p_physp))) {
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
						"ERR 0F08: "
						"DR path with hop count %d couldn't be extended\n",
						path.hop_count);
					break;
				}

				memset(&context, 0, sizeof(context));
				context.ni_context.node_guid =
				    osm_node_get_node_guid(p_node);
				context.ni_context.port_num =
				    osm_physp_get_port_num(p_physp);

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

				if (status != IB_SUCCESS)
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
						"ERR 0F02: "
						"Failure initiating NodeInfo request (%s)\n",
						ib_get_err_str(status));
			} else
				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
					"Skipping SMP responder port %u\n",
					p_pi->local_port_num);
		}
		break;

	default:
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0F03: "
			"Unknown link state = %u, port = %u\n",
			ib_port_info_get_port_state(p_pi),
			p_pi->local_port_num);
		break;
	}

	if (ib_port_info_get_port_state(p_pi) > IB_LINK_INIT && p_node->sw &&
	    !ib_switch_info_get_state_change(&p_node->sw->switch_info) &&
	    p_node->sw->need_update == 1)
		p_node->sw->need_update = 0;

	if (p_physp->need_update)
		sm->p_subn->ignore_existing_lfts = TRUE;

	/*
	   Update the PortInfo attribute.
	 */
	osm_physp_set_port_info(p_physp, p_pi, sm);

	if (ib_port_info_get_port_state(p_pi) == IB_LINK_DOWN)
		goto Exit;

	p_remote_physp = osm_physp_get_remote(p_physp);
	if (p_remote_physp) {
		p_remote_node = osm_physp_get_node_ptr(p_remote_physp);
		if (p_remote_node->sw) {
			data_vls = 1U << (ib_port_info_get_vl_cap(p_pi) - 1);
			if (data_vls > 1U << (sm->p_subn->opt.max_op_vls - 1))
				data_vls = 1U << (sm->p_subn->opt.max_op_vls - 1);
			if (data_vls >= IB_MAX_NUM_VLS)
				data_vls = IB_MAX_NUM_VLS - 1;
			if ((uint8_t)data_vls < sm->p_subn->min_sw_data_vls) {
				OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
					"Setting switch port minimal data VLs "
					"to:%u defined by node:0x%"
					PRIx64 ", port:%u\n", data_vls,
					cl_ntoh64(osm_node_get_node_guid(p_node)),
					port_num);
				sm->p_subn->min_sw_data_vls = data_vls;
			}
		}
	}

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

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_sw);

	p_node = p_sw->p_node;

	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);

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

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

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

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

	max_position = osm_mcast_tbl_get_max_position(p_tbl);

	CL_ASSERT(max_position <= IB_MCAST_POSITION_MAX);

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

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

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

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

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

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
예제 #15
0
static boolean_t
__osm_link_mgr_set_physp_pi(osm_sm_t * sm,
			    IN osm_physp_t * const p_physp,
			    IN uint8_t const port_state)
{
	uint8_t payload[IB_SMP_DATA_SIZE];
	ib_port_info_t *const p_pi = (ib_port_info_t *) payload;
	const ib_port_info_t *p_old_pi;
	osm_madw_context_t context;
	osm_node_t *p_node;
	ib_api_status_t status;
	uint8_t port_num;
	uint8_t mtu;
	uint8_t op_vls;
	boolean_t esp0 = FALSE;
	boolean_t send_set = FALSE;
	osm_physp_t *p_remote_physp;

	OSM_LOG_ENTER(sm->p_log);

	p_node = osm_physp_get_node_ptr(p_physp);

	port_num = osm_physp_get_port_num(p_physp);

	if (port_num == 0) {
		/*
		   CAs don't have a port 0, and for switch port 0,
		   we need to check if this is enhanced or base port 0.
		   For base port 0 the following parameters are not valid (p822, table 145).
		 */
		if (!p_node->sw) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: "
				"Cannot find switch by guid: 0x%" PRIx64 "\n",
				cl_ntoh64(p_node->node_info.node_guid));
			goto Exit;
		}

		if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)
		    == FALSE) {
			/* This means the switch doesn't support enhanced port 0.
			   Can skip it. */
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Skipping port 0, GUID 0x%016" PRIx64 "\n",
				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
			goto Exit;
		}
		esp0 = TRUE;
	}

	/*
	   PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
	 */

	p_old_pi = &p_physp->port_info;

	memset(payload, 0, IB_SMP_DATA_SIZE);
	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));

	/*
	   Should never write back a value that is bigger then 3 in
	   the PortPhysicalState field - so can not simply copy!

	   Actually we want to write there:
	   port physical state - no change,
	   link down default state = polling
	   port state - as requested.
	 */
	p_pi->state_info2 = 0x02;
	ib_port_info_set_port_state(p_pi, port_state);

	if (ib_port_info_get_link_down_def_state(p_pi) !=
	    ib_port_info_get_link_down_def_state(p_old_pi))
		send_set = TRUE;

	/* didn't get PortInfo before */
	if (!ib_port_info_get_port_state(p_old_pi))
		send_set = TRUE;

	/* we only change port fields if we do not change state */
	if (port_state == IB_LINK_NO_CHANGE) {
		/* The following fields are relevant only for CA port, router, or Enh. SP0 */
		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
		    port_num == 0) {
			p_pi->m_key = sm->p_subn->opt.m_key;
			if (memcmp(&p_pi->m_key, &p_old_pi->m_key,
				   sizeof(p_pi->m_key)))
				send_set = TRUE;

			p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix;
			if (memcmp(&p_pi->subnet_prefix,
				   &p_old_pi->subnet_prefix,
				   sizeof(p_pi->subnet_prefix)))
				send_set = TRUE;

			p_pi->base_lid = osm_physp_get_base_lid(p_physp);
			if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid,
				   sizeof(p_pi->base_lid)))
				send_set = TRUE;

			/* we are initializing the ports with our local sm_base_lid */
			p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid;
			if (memcmp(&p_pi->master_sm_base_lid,
				   &p_old_pi->master_sm_base_lid,
				   sizeof(p_pi->master_sm_base_lid)))
				send_set = TRUE;

			p_pi->m_key_lease_period =
			    sm->p_subn->opt.m_key_lease_period;
			if (memcmp(&p_pi->m_key_lease_period,
				   &p_old_pi->m_key_lease_period,
				   sizeof(p_pi->m_key_lease_period)))
				send_set = TRUE;

			if (esp0 == FALSE)
				p_pi->mkey_lmc = sm->p_subn->opt.lmc;
			else {
				if (sm->p_subn->opt.lmc_esp0)
					p_pi->mkey_lmc = sm->p_subn->opt.lmc;
				else
					p_pi->mkey_lmc = 0;
			}
			if (memcmp(&p_pi->mkey_lmc, &p_old_pi->mkey_lmc,
				   sizeof(p_pi->mkey_lmc)))
				send_set = TRUE;

			ib_port_info_set_timeout(p_pi,
						 sm->p_subn->opt.
						 subnet_timeout);
			if (ib_port_info_get_timeout(p_pi) !=
			    ib_port_info_get_timeout(p_old_pi))
				send_set = TRUE;
		}

		/*
		   Several timeout mechanisms:
		 */
		p_remote_physp = osm_physp_get_remote(p_physp);
		if (port_num != 0 && p_remote_physp) {
			if (osm_node_get_type(osm_physp_get_node_ptr(p_physp))
			    == IB_NODE_TYPE_ROUTER) {
				ib_port_info_set_hoq_lifetime(p_pi,
							      sm->p_subn->
							      opt.
							      leaf_head_of_queue_lifetime);
			} else
			    if (osm_node_get_type
				(osm_physp_get_node_ptr(p_physp)) ==
				IB_NODE_TYPE_SWITCH) {
				/* Is remote end CA or router (a leaf port) ? */
				if (osm_node_get_type
				    (osm_physp_get_node_ptr(p_remote_physp)) !=
				    IB_NODE_TYPE_SWITCH) {
					ib_port_info_set_hoq_lifetime(p_pi,
								      sm->
								      p_subn->
								      opt.
								      leaf_head_of_queue_lifetime);
					ib_port_info_set_vl_stall_count(p_pi,
									sm->
									p_subn->
									opt.
									leaf_vl_stall_count);
				} else {
					ib_port_info_set_hoq_lifetime(p_pi,
								      sm->
								      p_subn->
								      opt.
								      head_of_queue_lifetime);
					ib_port_info_set_vl_stall_count(p_pi,
									sm->
									p_subn->
									opt.
									vl_stall_count);
				}
			}
			if (ib_port_info_get_hoq_lifetime(p_pi) !=
			    ib_port_info_get_hoq_lifetime(p_old_pi) ||
			    ib_port_info_get_vl_stall_count(p_pi) !=
			    ib_port_info_get_vl_stall_count(p_old_pi))
				send_set = TRUE;
		}

		ib_port_info_set_phy_and_overrun_err_thd(p_pi,
							 sm->p_subn->opt.
							 local_phy_errors_threshold,
							 sm->p_subn->opt.
							 overrun_errors_threshold);
		if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold,
			   sizeof(p_pi->error_threshold)))
			send_set = TRUE;

		/*
		   Set the easy common parameters for all port types,
		   then determine the neighbor MTU.
		 */
		p_pi->link_width_enabled = p_old_pi->link_width_supported;
		if (memcmp(&p_pi->link_width_enabled,
			   &p_old_pi->link_width_enabled,
			   sizeof(p_pi->link_width_enabled)))
			send_set = TRUE;

		if (sm->p_subn->opt.force_link_speed &&
		    (sm->p_subn->opt.force_link_speed != 15 ||
		     ib_port_info_get_link_speed_enabled(p_pi) !=
		     ib_port_info_get_link_speed_sup(p_pi))) {
			ib_port_info_set_link_speed_enabled(p_pi,
							    sm->p_subn->opt.
							    force_link_speed);
			if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed,
				   sizeof(p_pi->link_speed)))
				send_set = TRUE;
		}

		/* calc new op_vls and mtu */
		op_vls =
		    osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp);
		mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp);

		ib_port_info_set_neighbor_mtu(p_pi, mtu);
		if (ib_port_info_get_neighbor_mtu(p_pi) !=
		    ib_port_info_get_neighbor_mtu(p_old_pi))
			send_set = TRUE;

		ib_port_info_set_op_vls(p_pi, op_vls);
		if (ib_port_info_get_op_vls(p_pi) !=
		    ib_port_info_get_op_vls(p_old_pi))
			send_set = TRUE;

		/* provide the vl_high_limit from the qos mgr */
		if (sm->p_subn->opt.qos &&
		    p_physp->vl_high_limit != p_old_pi->vl_high_limit) {
			send_set = TRUE;
			p_pi->vl_high_limit = p_physp->vl_high_limit;
		}
	}

	if (port_state != IB_LINK_NO_CHANGE &&
	    port_state != ib_port_info_get_port_state(p_old_pi)) {
		send_set = TRUE;
		if (port_state == IB_LINK_ACTIVE)
			context.pi_context.active_transition = TRUE;
		else
			context.pi_context.active_transition = FALSE;
	}

	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
	context.pi_context.set_method = TRUE;
	context.pi_context.light_sweep = FALSE;

	/* We need to send the PortInfoSet request with the new sm_lid
	   in the following cases:
	   1. There is a change in the values (send_set == TRUE)
	   2. This is a switch external port (so it wasn't handled yet by
	   osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE,
	   which means the SM just became master, and it then needs to send at
	   PortInfoSet to every port.
	 */
	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num
	    && sm->p_subn->first_time_master_sweep == TRUE)
		send_set = TRUE;

	if (send_set)
		status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
				     payload, sizeof(payload),
				     IB_MAD_ATTR_PORT_INFO,
				     cl_hton32(port_num),
				     CL_DISP_MSGID_NONE, &context);

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return send_set;
}
예제 #16
0
static int link_mgr_set_physp_pi(osm_sm_t * sm, IN osm_physp_t * p_physp,
				 IN uint8_t port_state)
{
	uint8_t payload[IB_SMP_DATA_SIZE], payload2[IB_SMP_DATA_SIZE];
	ib_port_info_t *p_pi = (ib_port_info_t *) payload;
	ib_mlnx_ext_port_info_t *p_epi = (ib_mlnx_ext_port_info_t *) payload2;
	const ib_port_info_t *p_old_pi;
	const ib_mlnx_ext_port_info_t *p_old_epi;
	osm_madw_context_t context;
	osm_node_t *p_node;
	ib_api_status_t status;
	uint8_t port_num, mtu, op_vls, smsl = OSM_DEFAULT_SL;
	boolean_t esp0 = FALSE, send_set = FALSE, send_set2 = FALSE;
	osm_physp_t *p_remote_physp, *physp0;
	int qdr_change = 0, fdr10_change = 0;
	int ret = 0;
	ib_net32_t attr_mod, cap_mask;

	OSM_LOG_ENTER(sm->p_log);

	p_node = osm_physp_get_node_ptr(p_physp);

	p_old_pi = &p_physp->port_info;

	port_num = osm_physp_get_port_num(p_physp);

	if (port_num == 0) {
		/*
		   CAs don't have a port 0, and for switch port 0,
		   we need to check if this is enhanced or base port 0.
		   For base port 0 the following parameters are not valid
		   (IBA 1.2.1 p.830 table 146).
		 */
		if (!p_node->sw) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 4201: "
				"Cannot find switch by guid: 0x%" PRIx64 "\n",
				cl_ntoh64(p_node->node_info.node_guid));
			goto Exit;
		}

		if (ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info)
		    == FALSE) {

			/* Even for base port 0 we might have to set smsl
			   (if we are using lash routing) */
			smsl = link_mgr_get_smsl(sm, p_physp);
			if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {
				send_set = TRUE;
				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
					"Setting SMSL to %d on port 0 GUID 0x%016"
					PRIx64 "\n", smsl,
					cl_ntoh64(osm_physp_get_port_guid
						  (p_physp)));
			} else {
				/* This means the switch doesn't support
				   enhanced port 0 and we don't need to
				   change SMSL. Can skip it. */
				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
					"Skipping port 0, GUID 0x%016" PRIx64
					"\n",
					cl_ntoh64(osm_physp_get_port_guid
						  (p_physp)));
				goto Exit;
			}
		} else
			esp0 = TRUE;
	}

	memcpy(payload, p_old_pi, sizeof(ib_port_info_t));

	/*
	   Should never write back a value that is bigger then 3 in
	   the PortPhysicalState field - so can not simply copy!

	   Actually we want to write there:
	   port physical state - no change,
	   link down default state = polling
	   port state - as requested.
	 */
	p_pi->state_info2 = 0x02;
	ib_port_info_set_port_state(p_pi, port_state);

	/* Check whether this is base port0 smsl handling only */
	if (port_num == 0 && esp0 == FALSE) {
		ib_port_info_set_master_smsl(p_pi, smsl);
		goto Send;
	}

	/*
	   PAST THIS POINT WE ARE HANDLING EITHER A NON PORT 0 OR ENHANCED PORT 0
	 */

	if (ib_port_info_get_link_down_def_state(p_pi) !=
	    ib_port_info_get_link_down_def_state(p_old_pi))
		send_set = TRUE;

	/* didn't get PortInfo before */
	if (!ib_port_info_get_port_state(p_old_pi))
		send_set = TRUE;

	/* we only change port fields if we do not change state */
	if (port_state == IB_LINK_NO_CHANGE) {
		/* The following fields are relevant only for CA port, router, or Enh. SP0 */
		if (osm_node_get_type(p_node) != IB_NODE_TYPE_SWITCH ||
		    port_num == 0) {
			p_pi->m_key = sm->p_subn->opt.m_key;
			if (memcmp(&p_pi->m_key, &p_old_pi->m_key,
				   sizeof(p_pi->m_key)))
				send_set = TRUE;

			p_pi->subnet_prefix = sm->p_subn->opt.subnet_prefix;
			if (memcmp(&p_pi->subnet_prefix,
				   &p_old_pi->subnet_prefix,
				   sizeof(p_pi->subnet_prefix)))
				send_set = TRUE;

			p_pi->base_lid = osm_physp_get_base_lid(p_physp);
			if (memcmp(&p_pi->base_lid, &p_old_pi->base_lid,
				   sizeof(p_pi->base_lid)))
				send_set = TRUE;

			/* we are initializing the ports with our local sm_base_lid */
			p_pi->master_sm_base_lid = sm->p_subn->sm_base_lid;
			if (memcmp(&p_pi->master_sm_base_lid,
				   &p_old_pi->master_sm_base_lid,
				   sizeof(p_pi->master_sm_base_lid)))
				send_set = TRUE;

			smsl = link_mgr_get_smsl(sm, p_physp);
			if (smsl != ib_port_info_get_master_smsl(p_old_pi)) {

				ib_port_info_set_master_smsl(p_pi, smsl);

				OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
					"Setting SMSL to %d on GUID 0x%016"
					PRIx64 ", port %d\n", smsl,
					cl_ntoh64(osm_physp_get_port_guid
						  (p_physp)), port_num);

				send_set = TRUE;
			}

			p_pi->m_key_lease_period =
			    sm->p_subn->opt.m_key_lease_period;
			if (memcmp(&p_pi->m_key_lease_period,
				   &p_old_pi->m_key_lease_period,
				   sizeof(p_pi->m_key_lease_period)))
				send_set = TRUE;

			/* M_KeyProtectBits are currently always zero */
			p_pi->mkey_lmc = 0;
			if (esp0 == FALSE || sm->p_subn->opt.lmc_esp0)
				ib_port_info_set_lmc(p_pi, sm->p_subn->opt.lmc);
			if (ib_port_info_get_lmc(p_old_pi) !=
			    ib_port_info_get_lmc(p_pi) ||
			    ib_port_info_get_mpb(p_old_pi) !=
			    ib_port_info_get_mpb(p_pi))
				send_set = TRUE;

			ib_port_info_set_timeout(p_pi,
						 sm->p_subn->opt.
						 subnet_timeout);
			if (ib_port_info_get_timeout(p_pi) !=
			    ib_port_info_get_timeout(p_old_pi))
				send_set = TRUE;
		}

		/*
		   Several timeout mechanisms:
		 */
		p_remote_physp = osm_physp_get_remote(p_physp);
		if (port_num != 0 && p_remote_physp) {
			if (osm_node_get_type(osm_physp_get_node_ptr(p_physp))
			    == IB_NODE_TYPE_ROUTER) {
				ib_port_info_set_hoq_lifetime(p_pi,
							      sm->p_subn->
							      opt.
							      leaf_head_of_queue_lifetime);
			} else
			    if (osm_node_get_type
				(osm_physp_get_node_ptr(p_physp)) ==
				IB_NODE_TYPE_SWITCH) {
				/* Is remote end CA or router (a leaf port) ? */
				if (osm_node_get_type
				    (osm_physp_get_node_ptr(p_remote_physp)) !=
				    IB_NODE_TYPE_SWITCH) {
					ib_port_info_set_hoq_lifetime(p_pi,
								      sm->
								      p_subn->
								      opt.
								      leaf_head_of_queue_lifetime);
					ib_port_info_set_vl_stall_count(p_pi,
									sm->
									p_subn->
									opt.
									leaf_vl_stall_count);
				} else {
					ib_port_info_set_hoq_lifetime(p_pi,
								      sm->
								      p_subn->
								      opt.
								      head_of_queue_lifetime);
					ib_port_info_set_vl_stall_count(p_pi,
									sm->
									p_subn->
									opt.
									vl_stall_count);
				}
			}
			if (ib_port_info_get_hoq_lifetime(p_pi) !=
			    ib_port_info_get_hoq_lifetime(p_old_pi) ||
			    ib_port_info_get_vl_stall_count(p_pi) !=
			    ib_port_info_get_vl_stall_count(p_old_pi))
				send_set = TRUE;
		}

		ib_port_info_set_phy_and_overrun_err_thd(p_pi,
							 sm->p_subn->opt.
							 local_phy_errors_threshold,
							 sm->p_subn->opt.
							 overrun_errors_threshold);
		if (memcmp(&p_pi->error_threshold, &p_old_pi->error_threshold,
			   sizeof(p_pi->error_threshold)))
			send_set = TRUE;

		/*
		   Set the easy common parameters for all port types,
		   then determine the neighbor MTU.
		 */
		p_pi->link_width_enabled = p_old_pi->link_width_supported;
		if (memcmp(&p_pi->link_width_enabled,
			   &p_old_pi->link_width_enabled,
			   sizeof(p_pi->link_width_enabled)))
			send_set = TRUE;

		if (sm->p_subn->opt.force_link_speed &&
		    (sm->p_subn->opt.force_link_speed != 15 ||
		     ib_port_info_get_link_speed_enabled(p_pi) !=
		     ib_port_info_get_link_speed_sup(p_pi))) {
			ib_port_info_set_link_speed_enabled(p_pi,
							    sm->p_subn->opt.
							    force_link_speed);
			if (memcmp(&p_pi->link_speed, &p_old_pi->link_speed,
				   sizeof(p_pi->link_speed))) {
				send_set = TRUE;
				/* Determine whether QDR in LSE is being changed */
				if ((ib_port_info_get_link_speed_enabled(p_pi) &
				     IB_LINK_SPEED_ACTIVE_10 &&
				     !(ib_port_info_get_link_speed_enabled(p_old_pi) &
				      IB_LINK_SPEED_ACTIVE_10)) ||
				    ((!(ib_port_info_get_link_speed_enabled(p_pi) &
				       IB_LINK_SPEED_ACTIVE_10) &&
				      ib_port_info_get_link_speed_enabled(p_old_pi) &
				      IB_LINK_SPEED_ACTIVE_10)))
				qdr_change = 1;
			}
		}

		if (sm->p_subn->opt.fdr10 &&
		    p_physp->ext_port_info.link_speed_supported & FDR10) {
			if (sm->p_subn->opt.fdr10 == 1) { /* enable */
				if (!(p_physp->ext_port_info.link_speed_enabled & FDR10))
					fdr10_change = 1;
			} else {	/* disable */
				if (p_physp->ext_port_info.link_speed_enabled & FDR10)
					fdr10_change = 1;
			}
			if (fdr10_change) {
				p_old_epi = &p_physp->ext_port_info;
				memcpy(payload2, p_old_epi,
				       sizeof(ib_mlnx_ext_port_info_t));
				p_epi->state_change_enable = 0x01;
				if (sm->p_subn->opt.fdr10 == 1)
					p_epi->link_speed_enabled = FDR10;
				else
					p_epi->link_speed_enabled = 0;
				send_set2 = TRUE;
			}
		}

		if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) {
			physp0 = osm_node_get_physp_ptr(p_physp->p_node, 0);
			cap_mask = physp0->port_info.capability_mask;
		} else
			cap_mask = p_pi->capability_mask;
		if (!(cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS))
			qdr_change = 0;

		/* Do peer ports support extended link speeds ? */
		if (port_num != 0 && p_remote_physp) {
			osm_physp_t *rphysp0;
			ib_net32_t rem_cap_mask;

			if (osm_node_get_type(p_remote_physp->p_node) ==
			    IB_NODE_TYPE_SWITCH) {
				rphysp0 = osm_node_get_physp_ptr(p_remote_physp->p_node, 0);
				rem_cap_mask = rphysp0->port_info.capability_mask;
			} else
				rem_cap_mask = p_remote_physp->port_info.capability_mask;

			if (cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS &&
			    rem_cap_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) {
				if (sm->p_subn->opt.force_link_speed_ext &&
				    (sm->p_subn->opt.force_link_speed_ext != IB_LINK_SPEED_EXT_SET_LSES ||
				     p_pi->link_speed_ext_enabled !=
				     ib_port_info_get_link_speed_sup(p_pi))) {
					p_pi->link_speed_ext_enabled = sm->p_subn->opt.force_link_speed_ext;
					if (memcmp(&p_pi->link_speed_ext_enabled,
						   &p_old_pi->link_speed_ext_enabled,
						   sizeof(p_pi->link_speed_ext_enabled)))
						send_set = TRUE;
				}
			}
		}

		/* calc new op_vls and mtu */
		op_vls =
		    osm_physp_calc_link_op_vls(sm->p_log, sm->p_subn, p_physp);
		mtu = osm_physp_calc_link_mtu(sm->p_log, p_physp);

		ib_port_info_set_neighbor_mtu(p_pi, mtu);
		if (ib_port_info_get_neighbor_mtu(p_pi) !=
		    ib_port_info_get_neighbor_mtu(p_old_pi))
			send_set = TRUE;

		ib_port_info_set_op_vls(p_pi, op_vls);
		if (ib_port_info_get_op_vls(p_pi) !=
		    ib_port_info_get_op_vls(p_old_pi))
			send_set = TRUE;

		/* provide the vl_high_limit from the qos mgr */
		if (sm->p_subn->opt.qos &&
		    p_physp->vl_high_limit != p_old_pi->vl_high_limit) {
			send_set = TRUE;
			p_pi->vl_high_limit = p_physp->vl_high_limit;
		}
	}

Send:
	if (port_state != IB_LINK_NO_CHANGE &&
	    port_state != ib_port_info_get_port_state(p_old_pi)) {
		send_set = TRUE;
		if (port_state == IB_LINK_ACTIVE)
			context.pi_context.active_transition = TRUE;
		else
			context.pi_context.active_transition = FALSE;
	}

	context.pi_context.node_guid = osm_node_get_node_guid(p_node);
	context.pi_context.port_guid = osm_physp_get_port_guid(p_physp);
	context.pi_context.set_method = TRUE;
	context.pi_context.light_sweep = FALSE;

	/* We need to send the PortInfoSet request with the new sm_lid
	   in the following cases:
	   1. There is a change in the values (send_set == TRUE)
	   2. This is a switch external port (so it wasn't handled yet by
	   osm_lid_mgr) and first_time_master_sweep flag on the subnet is TRUE,
	   which means the SM just became master, and it then needs to send at
	   PortInfoSet to every port.
	 */
	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH && port_num
	    && sm->p_subn->first_time_master_sweep == TRUE)
		send_set = TRUE;

	if (!send_set)
		goto Exit;

	attr_mod = cl_hton32(port_num);
	if (qdr_change)
		attr_mod |= cl_hton32(1 << 31);	/* AM SMSupportExtendedSpeeds */
	status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
			     payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
			     attr_mod, CL_DISP_MSGID_NONE, &context);
	if (status)
		ret = -1;

	if (send_set2) {
		status = osm_req_set(sm, osm_physp_get_dr_path_ptr(p_physp),
				     payload2, sizeof(payload2),
				     IB_MAD_ATTR_MLNX_EXTENDED_PORT_INFO,
				     cl_hton32(port_num),
				     CL_DISP_MSGID_NONE, &context);
		if (status)
			ret = -1;
	}

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return ret;
}
예제 #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
/*
 * Register/Unregister to receive the given InformInfo
 *
 * Uses the qp context to send the inform info mad.
 * Wait for GetResp(InformInfoResp)
 *
 */
ib_api_status_t
osmt_reg_unreg_inform_info(IN osmtest_t * p_osmt,
			   IN osmt_qp_ctx_t * p_qp_ctx,
			   IN ib_inform_info_t * p_inform_info,
			   IN uint8_t reg_flag)
{
	ib_sa_mad_t *p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_send_buf);
	ib_inform_info_t *p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);	/*  SA Payload */
	VAPI_ret_t vapi_ret;
	VAPI_wc_desc_t wc_desc;
	VAPI_ud_av_hndl_t avh;
	static VAPI_wr_id_t wrid = 16198;
	osm_log_t *p_log = &p_osmt->log;
	ib_api_status_t status = IB_SUCCESS;

	OSM_LOG_ENTER(&p_osmt->log);

	/* init the MAD */
	ib_mad_init_new((ib_mad_t *) p_sa_mad,
			IB_MCLASS_SUBN_ADM,
			(uint8_t) 2,
			IB_MAD_METHOD_SET, cl_hton64(wrid), (ib_net16_t) 0, 0);
	wrid++;
	p_sa_mad->attr_id = IB_MAD_ATTR_INFORM_INFO;

	/* copy the reference inform info */
	memcpy(p_ii, p_inform_info, sizeof(ib_inform_info_t));

	if (reg_flag) {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"Subscribing InformInfo: Traps from lid:0x%X to 0x%X, trap num :0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end,
			p_ii->g_or_v.generic.trap_num);
	} else {
		OSM_LOG(&p_osmt->log, OSM_LOG_INFO,
			"UnSubscribing InformInfo: Traps from lid:0x%X to 0x%X\n",
			p_ii->lid_range_begin, p_ii->lid_range_end);
	}

	/* set the subscribe bit */
	if (reg_flag) {
		p_ii->subscribe = 1;
	} else {
		p_ii->subscribe = 0;
		/*
		 * we need to set the QPN on the mad if we unsubscribe:
		 * o13-2.1.1 - QPN Field need to be set when unsubscribing.
		 */
		ib_inform_info_set_qpn(p_ii,
				       cl_hton32(p_qp_ctx->qp_bind_hndl.qp_id.
						 qp_num));
	}

	osm_dump_inform_info(&p_osmt->log, p_ii, OSM_LOG_DEBUG);

	/* --------------------- PREP ------------------------- */
	if (osmt_mtl_mad_post_recv_bufs(&p_qp_ctx->qp_bind_hndl, p_qp_ctx->p_recv_buf, 1,	/*  but we need only one mad at a time */
					GRH_LEN + MAD_BLOCK_SIZE, wrid) != 1) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0120: "
			"Error posting recv bufs\n");
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Posted recv bufs\n");

	vapi_ret =
	    osmt_mtl_create_av(&p_qp_ctx->qp_bind_hndl,
			       p_osmt->local_port.sm_lid, &avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0121: "
			"Error Preparing AVH (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Prepared AVH\n");

	if (osm_log_is_active(p_log, OSM_LOG_DEBUG)) {
		osm_dump_sa_mad(p_log, (ib_sa_mad_t *) (p_qp_ctx->p_send_buf),
				OSM_LOG_DEBUG);
#if 0
		for (i = 56; i < 253; i++) {
			if (i % 8 == 0) {
				printf("\n %d : ", i);
			}
			printf("0x%02X ", p_qp_ctx->p_send_buf[i]);
		}
#endif
		printf("\n");
	}

	/* --------------------- SEND ------------------------- */
	vapi_ret = osmt_mtl_mad_send(&p_qp_ctx->qp_bind_hndl, wrid, p_qp_ctx->p_send_buf, 1,	/*  SA is QP1 */
				     0,	/*  SL is 0 */
				     OSMT_MTL_REVERSE_QP1_WELL_KNOWN_Q_KEY,
				     avh);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0122: "
			"Error sending mad (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.sq_cq_hndl,
					 &wc_desc, 20, 10000, NULL);
	if (vapi_ret != VAPI_OK) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0123: "
			"Error getting send completion (%s)\n",
			VAPI_strerror_sym(vapi_ret));
		status = IB_ERROR;
		goto Exit;
	}

	if (wc_desc.status != VAPI_SUCCESS) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0124: "
			"Error on send completion (%s) (%d)\n",
			VAPI_strerror_sym(wc_desc.status), wc_desc.status);
		status = IB_ERROR;
		goto Exit;
	}
	OSM_LOG(p_log, OSM_LOG_DEBUG, "Sent MAD\n");

	/* --------------------- RECV ------------------------- */
	vapi_ret = osmt_mtl_mad_poll4cqe(p_qp_ctx->qp_bind_hndl.hca_hndl,
					 p_qp_ctx->qp_bind_hndl.rq_cq_hndl,
					 &wc_desc, 20, 10000, &avh);
	if (vapi_ret != VAPI_SUCCESS) {
		if (vapi_ret == VAPI_CQ_EMPTY) {
			status = IB_TIMEOUT;
		} else {
			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0125: "
				"Error receiving mad (%s)\n",
				VAPI_strerror_sym(vapi_ret));
			status = IB_ERROR;
		}
		goto Exit;
	}

	/* check to see if successful - by examination of the subscribe bit */
	p_sa_mad = (ib_sa_mad_t *) (p_qp_ctx->p_recv_buf + GRH_LEN);

	if (p_sa_mad->status != IB_SUCCESS) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR, "Remote error = %s\n",
			ib_get_mad_status_str((ib_mad_t *) p_sa_mad));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->method != IB_MAD_METHOD_GET_RESP) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_METHOD_GET_RESP but got:(%X)\n",
			p_sa_mad->method);
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	if (p_sa_mad->attr_id != IB_MAD_ATTR_INFORM_INFO) {
		OSM_LOG(&p_osmt->log, OSM_LOG_ERROR,
			"Expected IB_MAD_ATTR_INFORM_INFO but got:(%X)\n",
			cl_ntoh16(p_sa_mad->attr_id));
		status = IB_REMOTE_ERROR;
		goto Exit;
	}

	p_ii = ib_sa_mad_get_payload_ptr(p_sa_mad);
	if (!p_ii->subscribe) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0126: "
			"Subscribe/Unsubscribe Failed\n");
		status = IB_REMOTE_ERROR;
	}

Exit:
	OSM_LOG_EXIT(&p_osmt->log);
	return status;
}
예제 #19
0
int osm_ucast_mgr_set_fwd_table(IN osm_ucast_mgr_t * const p_mgr,
				IN osm_switch_t * const p_sw)
{
	osm_node_t *p_node;
	osm_dr_path_t *p_path;
	osm_madw_context_t context;
	ib_api_status_t status;
	ib_switch_info_t si;
	uint16_t block_id_ho = 0;
	uint8_t block[IB_SMP_DATA_SIZE];
	boolean_t set_swinfo_require = FALSE;
	uint16_t lin_top;
	uint8_t life_state;

	CL_ASSERT(p_mgr);

	OSM_LOG_ENTER(p_mgr->p_log);

	CL_ASSERT(p_sw);

	p_node = p_sw->p_node;

	CL_ASSERT(p_node);

	p_path = osm_physp_get_dr_path_ptr(osm_node_get_physp_ptr(p_node, 0));

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

	/* check to see if the change state bit is on. If it is - then we
	   need to clear it. */
	if (ib_switch_info_get_state_change(&si))
		life_state = ((p_mgr->p_subn->opt.packet_life_time << 3)
			      | (si.life_state & IB_SWITCH_PSC)) & 0xfc;
	else
		life_state = (p_mgr->p_subn->opt.packet_life_time << 3) & 0xf8;

	if ((life_state != si.life_state)
	    || ib_switch_info_get_state_change(&si)) {
		set_swinfo_require = TRUE;
		si.life_state = life_state;
	}

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

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

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

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

	/*
	   Send linear forwarding table blocks to the switch
	   as long as the switch indicates it has blocks needing
	   configuration.
	 */

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

	if (!p_sw->new_lft) {
		/* any routing should provide the new_lft */
		CL_ASSERT(p_mgr->p_subn->opt.use_ucast_cache &&
			  p_mgr->cache_valid && !p_sw->need_update);
		goto Exit;
	}

	for (block_id_ho = 0;
	     osm_switch_get_lft_block(p_sw, block_id_ho, block);
	     block_id_ho++) {
		if (!p_sw->need_update &&
		    !memcmp(block,
			    p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
			    IB_SMP_DATA_SIZE))
			continue;

		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
			"Writing FT block %u\n", block_id_ho);

		status = osm_req_set(p_mgr->sm, p_path,
				     p_sw->new_lft + block_id_ho * IB_SMP_DATA_SIZE,
				     sizeof(block),
				     IB_MAD_ATTR_LIN_FWD_TBL,
				     cl_hton32(block_id_ho),
				     CL_DISP_MSGID_NONE, &context);

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

Exit:
	OSM_LOG_EXIT(p_mgr->p_log);
	return 0;
}