Exemple #1
0
/** =========================================================================
 */
void ep_port_tbl_rec_init(osm_physp_t *p_physp, struct ep_port_tbl_rec *p_rec)
{
	const ib_port_info_t *p_pi;
	const osm_physp_t *p_physp0;
	uint8_t is_fdr10_active;
	uint8_t is_switch;

	if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH &&
	    osm_physp_get_port_num(p_physp) > 0) {
		/* for SW external ports, port 0 Capability Mask is used  */
		p_physp0 = osm_node_get_physp_ptr((osm_node_t *)p_physp->p_node, 0);
		p_pi = &p_physp0->port_info;
	} else {
		p_pi = &p_physp->port_info;
	}

	is_fdr10_active = ((p_physp->ext_port_info.link_speed_active & FDR10) ? 0xff : 0) &
					  SSA_DB_PORT_IS_FDR10_ACTIVE_MASK;
	is_switch = ((osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) ? 0xff : 0) &
					  SSA_DB_PORT_IS_SWITCH_MASK;

	p_rec->pkey_tbl_offset		= 0;
	p_rec->pkey_tbl_size		= 0;
	p_rec->port_lid			= osm_physp_get_base_lid(p_physp);
	p_rec->port_num			= osm_physp_get_port_num(p_physp);
	p_rec->neighbor_mtu		= ib_port_info_get_neighbor_mtu(&p_physp->port_info);
	p_rec->rate			= ib_port_info_compute_rate(&p_physp->port_info,
								    p_pi->capability_mask & IB_PORT_CAP_HAS_EXT_SPEEDS) &
					  SSA_DB_PORT_RATE_MASK;
	p_rec->vl_enforce		= p_physp->port_info.vl_enforce;
	p_rec->rate			= (uint8_t) (p_rec->rate | is_fdr10_active | is_switch);
}
Exemple #2
0
static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp)
{
	osm_opensm_t *p_osm = sm->p_subn->p_osm;
	struct osm_routing_engine *re = p_osm->routing_engine_used;
	const osm_port_t *p_sm_port, *p_src_port;
	ib_net16_t slid;
	uint8_t sl;

	OSM_LOG_ENTER(sm->p_log);

	if (!(re && re->path_sl &&
	      (slid = osm_physp_get_base_lid(p_physp)))) {
		/*
		 * Use default SL if routing engine does not provide a
		 * path SL lookup callback.
		 */
		OSM_LOG_EXIT(sm->p_log);
		return sm->p_subn->opt.sm_sl;
	}

	/* Find osm_port of the SM itself = dest_port */
	p_sm_port = osm_get_port_by_lid(sm->p_subn, sm->p_subn->sm_base_lid);

	/* Find osm_port of the source = p_physp */
	p_src_port = osm_get_port_by_lid(sm->p_subn, slid);

	/* Call into routing engine to find proper SL */
	sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl,
			 p_src_port, p_sm_port);

	OSM_LOG_EXIT(sm->p_log);
	return sl;
}
Exemple #3
0
/** ===========================================================================
 */
static void extract_port(osm_physp_t *p_physp, uint16_t *p_lid_ho,
			 uint64_t pkey_base_offset, uint16_t pkey_tbl_size,
			 uint64_t *p_port_offset,
			 struct ssa_db_extract *p_ssa_db)
{
	struct ep_map_rec *p_map_rec;
	uint64_t rec_key;
	uint16_t lid_ho;

	if (p_lid_ho) {
		/* in case of switch port */
		rec_key = ep_rec_gen_key(*p_lid_ho,
					 osm_physp_get_port_num(p_physp));
		lid_ho = *p_lid_ho;
	} else {
		rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)),
					 osm_physp_get_port_num(p_physp));
		lid_ho = 0;
	}

	smdb_port_init(p_physp, pkey_base_offset, pkey_tbl_size,
			     htons(lid_ho),
			     &p_ssa_db->p_port_tbl[*p_port_offset]);
	p_map_rec = ep_map_rec_init(*p_port_offset);
	cl_qmap_insert(&p_ssa_db->ep_port_tbl, rec_key,
		       &p_map_rec->map_item);
	*p_port_offset = *p_port_offset + 1;
}
Exemple #4
0
static uint8_t link_mgr_get_smsl(IN osm_sm_t * sm, IN osm_physp_t * p_physp)
{
	osm_opensm_t *p_osm = sm->p_subn->p_osm;
	struct osm_routing_engine *re = p_osm->routing_engine_used;
	ib_net16_t slid;
	ib_net16_t smlid;
	uint8_t sl;

	OSM_LOG_ENTER(sm->p_log);

	if (!(re && re->path_sl &&
	      (slid = osm_physp_get_base_lid(p_physp)))) {
		/*
		 * Use default SL if routing engine does not provide a
		 * path SL lookup callback.
		 */
		OSM_LOG_EXIT(sm->p_log);
		return sm->p_subn->opt.sm_sl;
	}

	smlid = sm->p_subn->sm_base_lid;

	/* Call into routing engine to find proper SL */
	sl = re->path_sl(re->context, sm->p_subn->opt.sm_sl,
			 slid, smlid);

	OSM_LOG_EXIT(sm->p_log);
	return sl;
}
Exemple #5
0
/** =========================================================================
 */
void ep_guid_to_lid_tbl_rec_init(osm_port_t *p_port,
				 struct ep_guid_to_lid_tbl_rec *p_rec)
{
	p_rec->guid = osm_physp_get_port_guid(p_port->p_physp);
	p_rec->lid = osm_physp_get_base_lid(p_port->p_physp);
	p_rec->lmc = osm_physp_get_lmc(p_port->p_physp);
	p_rec->is_switch = (osm_node_get_type(p_port->p_node) == IB_NODE_TYPE_SWITCH);

	memset(&p_rec->pad, 0, sizeof(p_rec->pad));
}
Exemple #6
0
/** =========================================================================
 */
void ep_link_tbl_rec_init(osm_physp_t *p_physp, struct ep_link_tbl_rec *p_rec)
{
	osm_physp_t *p_remote_physp;

	if (osm_node_get_type(p_physp->p_node) == IB_NODE_TYPE_SWITCH) {
		p_rec->from_lid = osm_node_get_base_lid(p_physp->p_node, 0);
		p_rec->from_port_num = osm_physp_get_port_num(p_physp);
	} else {
		p_rec->from_lid = osm_physp_get_base_lid(p_physp);
		p_rec->from_port_num = 0;
	}

	p_remote_physp = osm_physp_get_remote(p_physp);

	if (osm_node_get_type(p_remote_physp->p_node) ==
						IB_NODE_TYPE_SWITCH) {
		p_rec->to_lid = osm_node_get_base_lid(p_remote_physp->p_node, 0);
		p_rec->to_port_num =osm_physp_get_port_num(p_remote_physp);
	} else {
		p_rec->to_lid = osm_physp_get_base_lid(p_remote_physp);
		p_rec->to_port_num = 0;
	}
	memset(&p_rec->pad, 0, sizeof(p_rec->pad));
}
Exemple #7
0
/**********************************************************************
 The lock must be held before calling this function.
**********************************************************************/
ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node,
					IN uint32_t port_num)
{
	osm_physp_t *p_physp;
	osm_physp_t *p_remote_physp;
	CL_ASSERT(port_num < p_node->physp_tbl_size);

	p_physp = osm_node_get_physp_ptr(p_node, port_num);
	if (p_physp) {
		p_remote_physp = osm_physp_get_remote(p_physp);
		return osm_physp_get_base_lid(p_remote_physp);
	}

	return 0;
}
Exemple #8
0
/** ===========================================================================
 */
static void extract_host_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset,
			      uint64_t *p_pkey_offset, uint64_t *p_port_offset,
			      uint64_t *p_link_offset,
			      struct ssa_db_extract *p_ssa_db)
{
	const osm_pkey_tbl_t *p_pkey_tbl;
	const ib_pkey_table_t *block;
	osm_physp_t *p_physp = p_port->p_physp;
	ib_net16_t pkey;
	uint16_t block_index, pkey_idx;

	p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
	for (block_index = 0; block_index < p_pkey_tbl->used_blocks;
	     block_index++) {
		block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
		if (!block)
			continue;
		for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
		     pkey_idx++) {
			pkey = block->pkey_entry[pkey_idx];
			if (ib_pkey_is_invalid(pkey))
				continue;

			p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey;
			*p_pkey_offset = *p_pkey_offset + 1;
		}
	}

	if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) {
		ssa_log_err(SSA_LOG_DEFAULT,
			    "ERROR - truncating number of pkeys "
			    "from %d to %d (maximum) for LID %u\n",
			    *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1,
			    ntohs(osm_physp_get_base_lid(p_physp)));
		*p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1;
	}

	extract_port(p_physp, NULL, htonll(*p_pkey_base_offset * sizeof(pkey)),
		     htons(*p_pkey_offset * sizeof(pkey)),
		     p_port_offset, p_ssa_db);

	if (!osm_physp_get_remote(p_physp))
		return;

	extract_link(p_physp, NULL, p_link_offset, p_ssa_db);
}
Exemple #9
0
/** ===========================================================================
 */
static void extract_link(osm_physp_t *p_physp, uint16_t *p_lid_ho,
			      uint64_t *p_link_offset,
			      struct ssa_db_extract *p_ssa_db)
{
	struct ep_map_rec *p_map_rec;
	uint64_t rec_key;

	if (p_lid_ho)
		rec_key = ep_rec_gen_key(*p_lid_ho,
					 osm_physp_get_port_num(p_physp));
	else
		rec_key = ep_rec_gen_key(ntohs(osm_physp_get_base_lid(p_physp)),
					 osm_physp_get_port_num(p_physp));

	smdb_link_init(p_physp, &p_ssa_db->p_link_tbl[*p_link_offset]);
	p_map_rec = ep_map_rec_init(*p_link_offset);
	cl_qmap_insert(&p_ssa_db->ep_link_tbl, rec_key, &p_map_rec->map_item);
	*p_link_offset = *p_link_offset + 1;
}
Exemple #10
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;
}
Exemple #11
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;
}
Exemple #12
0
/** ===========================================================================
 */
static void extract_switch_port(osm_port_t *p_port, uint64_t *p_pkey_base_offset,
				uint64_t *p_pkey_offset, uint64_t *p_port_offset,
				uint64_t *p_link_offset,
				struct ssa_db_extract *p_ssa_db)
{
	osm_node_t *p_node = p_port->p_physp->p_node;
	const osm_pkey_tbl_t *p_pkey_tbl;
	const ib_pkey_table_t *block;
	osm_physp_t *p_physp;
	uint32_t i;
	ib_net16_t pkey;
	uint16_t lid_ho, block_index, pkey_idx;

	for (i = 0; i < p_node->physp_tbl_size; i++) {
		p_physp = osm_node_get_physp_ptr(p_node, i);
		if (!p_physp)
			continue;

		/* TODO: add filtering for down ports */

		if (i == 0) {
			lid_ho = ntohs(osm_physp_get_base_lid(p_physp));

			p_pkey_tbl = osm_physp_get_pkey_tbl(p_physp);
			for (block_index = 0; block_index < p_pkey_tbl->used_blocks;
			     block_index++) {
				block = osm_pkey_tbl_block_get(p_pkey_tbl, block_index);
				if (!block)
					continue;
				for (pkey_idx = 0; pkey_idx < IB_NUM_PKEY_ELEMENTS_IN_BLOCK;
				     pkey_idx++) {
					pkey = block->pkey_entry[pkey_idx];
					if (ib_pkey_is_invalid(pkey))
						continue;

					p_ssa_db->p_pkey_tbl[*p_pkey_base_offset + *p_pkey_offset] = pkey;
					*p_pkey_offset = *p_pkey_offset + 1;
				}
			}

			if (*p_pkey_offset >= SSA_EXTRACT_PKEYS_MAX) {
				ssa_log_err(SSA_LOG_DEFAULT,
					    "ERROR - truncating number of pkeys "
					    "from %d to %d (maximum) for LID %u\n",
					    *p_pkey_offset, SSA_EXTRACT_PKEYS_MAX - 1, lid_ho);
				*p_pkey_offset = SSA_EXTRACT_PKEYS_MAX - 1;
			}

			extract_port(p_physp, &lid_ho,
				     htonll(*p_pkey_base_offset * sizeof(pkey)),
				     htons(*p_pkey_offset * sizeof(pkey)),
				     p_port_offset, p_ssa_db);
		} else {
			extract_port(p_physp, &lid_ho, 0, 0, p_port_offset,
				     p_ssa_db);
		}

		if (!osm_physp_get_remote(p_physp))
			continue;

		extract_link(p_physp, &lid_ho, p_link_offset, p_ssa_db);
	}
}
static ib_net16_t get_base_lid(IN const osm_physp_t * p_physp)
{
	if (p_physp->p_node->node_info.node_type == IB_NODE_TYPE_SWITCH)
		p_physp = osm_node_get_physp_ptr(p_physp->p_node, 0);
	return osm_physp_get_base_lid(p_physp);
}
void osm_ucast_cache_add_link(osm_ucast_mgr_t * p_mgr,
			      osm_physp_t * p_physp1, osm_physp_t * p_physp2)
{
	osm_node_t *p_node_1 = p_physp1->p_node, *p_node_2 = p_physp2->p_node;
	uint16_t lid_ho_1, lid_ho_2;

	OSM_LOG_ENTER(p_mgr->p_log);

	if (!p_mgr->cache_valid)
		goto Exit;

	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH &&
	    osm_node_get_type(p_node_2) != IB_NODE_TYPE_SWITCH) {
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Dropping CA-2-CA link\n");
		osm_ucast_cache_invalidate(p_mgr);
		goto Exit;
	}

	if ((osm_node_get_type(p_node_1) == IB_NODE_TYPE_SWITCH &&
	     !osm_node_get_physp_ptr(p_node_1, 0)) ||
	    (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH &&
	     !osm_node_get_physp_ptr(p_node_2, 0))) {
		/* we're caching a link when one of the nodes
		   has already been dropped and cached */
		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
			"Port %u <-> port %u: port0 on one of the nodes "
			"has already been dropped and cached\n",
			p_physp1->port_num, p_physp2->port_num);
		goto Exit;
	}

	/* One of the nodes is switch. Just for code
	   simplicity, make sure that it's the first node. */

	if (osm_node_get_type(p_node_1) != IB_NODE_TYPE_SWITCH) {
		osm_physp_t *tmp = p_physp1;
		p_physp1 = p_physp2;
		p_physp2 = tmp;
		p_node_1 = p_physp1->p_node;
		p_node_2 = p_physp2->p_node;
	}

	if (!p_node_1->sw) {
		/* something is wrong - we'd better not use cache */
		osm_ucast_cache_invalidate(p_mgr);
		goto Exit;
	}

	lid_ho_1 = cl_ntoh16(osm_node_get_base_lid(p_node_1, 0));

	if (osm_node_get_type(p_node_2) == IB_NODE_TYPE_SWITCH) {

		if (!p_node_2->sw) {
			/* something is wrong - we'd better not use cache */
			osm_ucast_cache_invalidate(p_mgr);
			goto Exit;
		}

		lid_ho_2 = cl_ntoh16(osm_node_get_base_lid(p_node_2, 0));

		/* lost switch-2-switch link - cache both sides */
		cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, FALSE);
		cache_add_sw_link(p_mgr, p_physp2, lid_ho_1, FALSE);
	} else {
		lid_ho_2 = cl_ntoh16(osm_physp_get_base_lid(p_physp2));

		/* lost link to CA/RTR - cache only switch side */
		cache_add_sw_link(p_mgr, p_physp1, lid_ho_2, TRUE);
	}

Exit:
	OSM_LOG_EXIT(p_mgr->p_log);
}				/* osm_ucast_cache_add_link() */