Exemple #1
0
static ib_api_status_t
osm_switch_init(IN osm_switch_t * const p_sw,
		IN osm_node_t * const p_node,
		IN const osm_madw_t * const p_madw)
{
	ib_api_status_t status = IB_SUCCESS;
	ib_switch_info_t *p_si;
	ib_smp_t *p_smp;
	uint8_t num_ports;
	uint32_t port_num;

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_si = (ib_switch_info_t *) ib_smp_get_payload_ptr(p_smp);
	num_ports = osm_node_get_num_physp(p_node);

	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO);

	p_sw->p_node = p_node;
	p_sw->switch_info = *p_si;
	p_sw->num_ports = num_ports;
	p_sw->need_update = 2;

	/* Initiate the linear forwarding table */

	if (!p_si->lin_cap) {
		/* This switch does not support linear forwarding tables */
		status = IB_UNSUPPORTED;
		goto Exit;
	}

	p_sw->lft = malloc(IB_LID_UCAST_END_HO + 1);
	if (!p_sw->lft) {
		status = IB_INSUFFICIENT_MEMORY;
		goto Exit;
	}

	/* Initialize the table to OSM_NO_PATH, which is "invalid port" */
	memset(p_sw->lft, OSM_NO_PATH, IB_LID_UCAST_END_HO + 1);

	p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports);
	if (p_sw->p_prof == NULL) {
		status = IB_INSUFFICIENT_MEMORY;
		goto Exit;
	}

	memset(p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports);

	status = osm_mcast_tbl_init(&p_sw->mcast_tbl,
				    osm_node_get_num_physp(p_node),
				    cl_ntoh16(p_si->mcast_cap));
	if (status != IB_SUCCESS)
		goto Exit;

	for (port_num = 0; port_num < num_ports; port_num++)
		osm_port_prof_construct(&p_sw->p_prof[port_num]);

Exit:
	return (status);
}
osm_switch_t *osm_switch_new(IN osm_node_t * p_node,
			     IN const osm_madw_t * p_madw)
{
	osm_switch_t *p_sw;
	ib_switch_info_t *p_si;
	ib_smp_t *p_smp;
	uint8_t num_ports;
	uint32_t port_num;

	CL_ASSERT(p_madw);
	CL_ASSERT(p_node);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_si = ib_smp_get_payload_ptr(p_smp);
	num_ports = osm_node_get_num_physp(p_node);

	CL_ASSERT(p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO);

	if (!p_si->lin_cap) /* The switch doesn't support LFT */
		return NULL;

	p_sw = malloc(sizeof(*p_sw));
	if (!p_sw)
		return NULL;

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

	p_sw->p_node = p_node;
	p_sw->switch_info = *p_si;
	p_sw->num_ports = num_ports;
	p_sw->need_update = 2;

	p_sw->p_prof = malloc(sizeof(*p_sw->p_prof) * num_ports);
	if (!p_sw->p_prof)
		goto err;

	memset(p_sw->p_prof, 0, sizeof(*p_sw->p_prof) * num_ports);

	osm_mcast_tbl_init(&p_sw->mcast_tbl, osm_node_get_num_physp(p_node),
			   cl_ntoh16(p_si->mcast_cap));

	for (port_num = 0; port_num < num_ports; port_num++)
		osm_port_prof_construct(&p_sw->p_prof[port_num]);

	return p_sw;

err:
	osm_switch_delete(&p_sw);
	return NULL;
}
Exemple #3
0
static ib_api_status_t sl2vl_update(osm_sm_t * sm, osm_port_t * p_port,
				    osm_physp_t * p, uint8_t port_num,
				    unsigned force_update,
				    const struct qos_config *qcfg)
{
	ib_api_status_t status;
	uint8_t i, num_ports;
	osm_physp_t *p_physp;

	if (osm_node_get_type(osm_physp_get_node_ptr(p)) == IB_NODE_TYPE_SWITCH) {
		if (ib_port_info_get_vl_cap(&p->port_info) == 1) {
			/* Check port 0's capability mask */
			p_physp = p_port->p_physp;
			if (!
			    (p_physp->port_info.
			     capability_mask & IB_PORT_CAP_HAS_SL_MAP))
				return IB_SUCCESS;
		}
		num_ports = osm_node_get_num_physp(osm_physp_get_node_ptr(p));
	} else {
		if (!(p->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP))
			return IB_SUCCESS;
		num_ports = 1;
	}

	for (i = 0; i < num_ports; i++) {
		status =
		    sl2vl_update_table(sm, p, i, port_num,
				       force_update, &qcfg->sl2vl);
		if (status != IB_SUCCESS)
			return status;
	}

	return IB_SUCCESS;
}
Exemple #4
0
static osm_signal_t
__osm_link_mgr_process_node(osm_sm_t * sm,
			    IN osm_node_t * const p_node,
			    IN const uint8_t link_state)
{
	uint32_t i;
	uint32_t num_physp;
	osm_physp_t *p_physp;
	uint8_t current_state;
	osm_signal_t signal = OSM_SIGNAL_DONE;

	OSM_LOG_ENTER(sm->p_log);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Node 0x%" PRIx64 " going to %s\n",
		cl_ntoh64(osm_node_get_node_guid(p_node)),
		ib_get_port_state_str(link_state));

	/*
	   Set the PortInfo for every Physical Port associated
	   with this Port.  Start iterating with port 1, since the linkstate
	   is not applicable to the management port on switches.
	 */
	num_physp = osm_node_get_num_physp(p_node);
	for (i = 0; i < num_physp; i++) {
		/*
		   Don't bother doing anything if this Physical Port is not valid.
		   or if the state of the port is already better then the
		   specified state.
		 */
		p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i);
		if (!p_physp)
			continue;

		current_state = osm_physp_get_port_state(p_physp);
		if (current_state == IB_LINK_DOWN)
			continue;

		/*
		   Normally we only send state update if state is lower
		   then required state. However, we need to send update if
		   no state change required.
		 */
		if (link_state != IB_LINK_NO_CHANGE &&
		    link_state <= current_state)
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Physical port %u already %s. Skipping\n",
				p_physp->port_num,
				ib_get_port_state_str(current_state));
		else if (__osm_link_mgr_set_physp_pi(sm, p_physp, link_state))
			signal = OSM_SIGNAL_DONE_PENDING;
	}

	OSM_LOG_EXIT(sm->p_log);
	return (signal);
}
Exemple #5
0
static void
__osm_ucast_mgr_process_neighbors(IN cl_map_item_t * const p_map_item,
				  IN void *context)
{
	osm_switch_t *const p_sw = (osm_switch_t *) p_map_item;
	osm_ucast_mgr_t *const p_mgr = (osm_ucast_mgr_t *) context;
	osm_node_t *p_node;
	osm_node_t *p_remote_node;
	uint32_t port_num;
	uint8_t remote_port_num;
	uint32_t num_ports;
	osm_physp_t *p_physp;

	OSM_LOG_ENTER(p_mgr->p_log);

	p_node = p_sw->p_node;

	CL_ASSERT(p_node);
	CL_ASSERT(osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH);

	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
		"Processing switch with GUID 0x%" PRIx64 "\n",
		cl_ntoh64(osm_node_get_node_guid(p_node)));

	num_ports = osm_node_get_num_physp(p_node);

	/*
	   Start with port 1 to skip the switch's management port.
	 */
	for (port_num = 1; port_num < num_ports; port_num++) {
		p_remote_node = osm_node_get_remote_node(p_node,
							 (uint8_t) port_num,
							 &remote_port_num);

		if (p_remote_node && p_remote_node->sw
		    && (p_remote_node != p_node)) {
			/* make sure the link is healthy. If it is not - don't
			   propagate through it. */
			p_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (!p_physp || !osm_link_is_healthy(p_physp))
				continue;

			__osm_ucast_mgr_process_neighbor(p_mgr, p_sw,
							 p_remote_node->sw,
							 (uint8_t) port_num,
							 remote_port_num);

		}
	}

	OSM_LOG_EXIT(p_mgr->p_log);
}
/**********************************************************************
 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);
}
static void osm_lash_process_switch(lash_t * p_lash, osm_switch_t * p_sw)
{
	osm_log_t *p_log = &p_lash->p_osm->log;
	int i, port_count;
	osm_physp_t *p_current_physp, *p_remote_physp;
	unsigned switch_a_lash_id, switch_b_lash_id;

	OSM_LOG_ENTER(p_log);

	switch_a_lash_id = get_lash_id(p_sw);
	port_count = osm_node_get_num_physp(p_sw->p_node);

	/* starting at port 1, ignoring management port on switch */
	for (i = 1; i < port_count; i++) {

		p_current_physp = osm_node_get_physp_ptr(p_sw->p_node, i);
		if (p_current_physp) {
			p_remote_physp = p_current_physp->p_remote_physp;
			if (p_remote_physp && p_remote_physp->p_node->sw) {
				int physical_port_a_num =
				    osm_physp_get_port_num(p_current_physp);
				int physical_port_b_num =
				    osm_physp_get_port_num(p_remote_physp);
				switch_b_lash_id =
				    get_lash_id(p_remote_physp->p_node->sw);

				connect_switches(p_lash, switch_a_lash_id,
						 switch_b_lash_id,
						 physical_port_a_num);
				OSM_LOG(p_log, OSM_LOG_VERBOSE,
					"LASH SUCCESS connected G 0x%016" PRIx64
					" , lash_id(%u), P(%u) " " to G 0x%016"
					PRIx64 " , lash_id(%u) , P(%u)\n",
					cl_ntoh64(osm_physp_get_port_guid
						  (p_current_physp)),
					switch_a_lash_id, physical_port_a_num,
					cl_ntoh64(osm_physp_get_port_guid
						  (p_remote_physp)),
					switch_b_lash_id, physical_port_b_num);
			}
		}
	}

	OSM_LOG_EXIT(p_log);
}
Exemple #8
0
static void state_mgr_update_node_desc(IN cl_map_item_t * obj, IN void *context)
{
	osm_madw_context_t mad_context;
	osm_node_t *p_node = (osm_node_t *) obj;
	osm_sm_t *sm = context;
	osm_physp_t *p_physp = NULL;
	unsigned i, num_ports;
	ib_api_status_t status;

	OSM_LOG_ENTER(sm->p_log);

	CL_ASSERT(p_node);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Updating NodeDesc for 0x%016" PRIx64 "\n",
		cl_ntoh64(osm_node_get_node_guid(p_node)));

	/* get a physp to request from. */
	num_ports = osm_node_get_num_physp(p_node);
	for (i = 0; i < num_ports; i++)
		if ((p_physp = osm_node_get_physp_ptr(p_node, i)))
			break;

	if (!p_physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 331C: "
			"Failed to find any valid physical port object.\n");
		goto exit;
	}

	mad_context.nd_context.node_guid = osm_node_get_node_guid(p_node);

	status = osm_req_get(sm, osm_physp_get_dr_path_ptr(p_physp),
			     IB_MAD_ATTR_NODE_DESC, 0, CL_DISP_MSGID_NONE,
			     &mad_context);
	if (status != IB_SUCCESS)
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 331B: Failure initiating NodeDescription request "
			"(%s)\n", ib_get_err_str(status));

exit:
	OSM_LOG_EXIT(sm->p_log);
}
Exemple #9
0
/**********************************************************************
 Initiates a lightweight sweep of the subnet.
 Used during normal sweeps after the subnet is up.
**********************************************************************/
static ib_api_status_t state_mgr_light_sweep_start(IN osm_sm_t * sm)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_bind_handle_t h_bind;
	cl_qmap_t *p_sw_tbl;
	cl_map_item_t *p_next;
	osm_node_t *p_node;
	osm_physp_t *p_physp;
	uint8_t port_num;

	OSM_LOG_ENTER(sm->p_log);

	p_sw_tbl = &sm->p_subn->sw_guid_tbl;

	/*
	 * First, get the bind handle.
	 */
	h_bind = osm_sm_mad_ctrl_get_bind_handle(&sm->mad_ctrl);
	if (h_bind == OSM_BIND_INVALID_HANDLE) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
			"No bound ports. Deferring sweep...\n");
		status = IB_INVALID_STATE;
		goto _exit;
	}

	OSM_LOG_MSG_BOX(sm->p_log, OSM_LOG_VERBOSE, "INITIATING LIGHT SWEEP");
	CL_PLOCK_ACQUIRE(sm->p_lock);
	cl_qmap_apply_func(p_sw_tbl, state_mgr_get_sw_info, sm);
	CL_PLOCK_RELEASE(sm->p_lock);

	CL_PLOCK_ACQUIRE(sm->p_lock);
	cl_qmap_apply_func(&sm->p_subn->node_guid_tbl, state_mgr_get_node_desc,
			   sm);
	CL_PLOCK_RELEASE(sm->p_lock);

	/* now scan the list of physical ports that were not down but have no remote port */
	CL_PLOCK_ACQUIRE(sm->p_lock);
	p_next = cl_qmap_head(&sm->p_subn->node_guid_tbl);
	while (p_next != cl_qmap_end(&sm->p_subn->node_guid_tbl)) {
		p_node = (osm_node_t *) p_next;
		p_next = cl_qmap_next(p_next);

		for (port_num = 1; port_num < osm_node_get_num_physp(p_node);
		     port_num++) {
			p_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (p_physp && (osm_physp_get_port_state(p_physp) !=
					IB_LINK_DOWN)
			    && !osm_physp_get_remote(p_physp)) {
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3315: "
					"Unknown remote side for node 0x%016"
					PRIx64
					" (%s) port %u. Adding to light sweep sampling list\n",
					cl_ntoh64(osm_node_get_node_guid
						  (p_node)),
					p_node->print_desc, port_num);

				osm_dump_dr_path(sm->p_log,
						 osm_physp_get_dr_path_ptr
						 (p_physp), OSM_LOG_ERROR);

				state_mgr_get_remote_port_info(sm, p_physp);
			}
		}
	}

	cl_qmap_apply_func(&sm->p_subn->sm_guid_tbl, query_sm_info, sm);

	CL_PLOCK_RELEASE(sm->p_lock);

_exit:
	OSM_LOG_EXIT(sm->p_log);
	return status;
}
Exemple #10
0
static void
__osm_sa_slvl_by_comp_mask(IN osm_sa_t * sa,
			   IN const osm_port_t * const p_port,
			   osm_slvl_search_ctxt_t * const p_ctxt)
{
	const ib_slvl_table_record_t *p_rcvd_rec;
	ib_net64_t comp_mask;
	const osm_physp_t *p_out_physp, *p_in_physp;
	uint8_t in_port_num, out_port_num;
	uint8_t num_ports;
	uint8_t in_port_start, in_port_end;
	uint8_t out_port_start, out_port_end;
	const osm_physp_t *p_req_physp;

	OSM_LOG_ENTER(sa->p_log);

	p_rcvd_rec = p_ctxt->p_rcvd_rec;
	comp_mask = p_ctxt->comp_mask;
	num_ports = osm_node_get_num_physp(p_port->p_node);
	in_port_start = 0;
	in_port_end = num_ports - 1;
	out_port_start = 0;
	out_port_end = num_ports - 1;
	p_req_physp = p_ctxt->p_req_physp;

	if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) {
		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"Using Physical Default Port Number: 0x%X (for End Node)\n",
			p_port->p_physp->port_num);
		p_out_physp = p_port->p_physp;
		/* check that the p_out_physp and the p_req_physp share a pkey */
		if (osm_physp_share_pkey
		    (sa->p_log, p_req_physp, p_out_physp))
			__osm_sa_slvl_create(sa, p_out_physp, p_ctxt, 0);
	} else {
		if (comp_mask & IB_SLVL_COMPMASK_OUT_PORT)
			out_port_start = out_port_end =
			    p_rcvd_rec->out_port_num;
		if (comp_mask & IB_SLVL_COMPMASK_IN_PORT)
			in_port_start = in_port_end = p_rcvd_rec->in_port_num;

		for (out_port_num = out_port_start;
		     out_port_num <= out_port_end; out_port_num++) {
			p_out_physp =
			    osm_node_get_physp_ptr(p_port->p_node,
						   out_port_num);
			if (!p_out_physp)
				continue;

			for (in_port_num = in_port_start;
			     in_port_num <= in_port_end; in_port_num++) {
#if 0
				if (out_port_num && out_port_num == in_port_num)
					continue;
#endif

				p_in_physp =
				    osm_node_get_physp_ptr(p_port->p_node,
							   in_port_num);
				if (!p_in_physp)
					continue;

				/* if the requester and the p_out_physp don't share a pkey -
				   continue */
				if (!osm_physp_share_pkey
				    (sa->p_log, p_req_physp, p_out_physp))
					continue;

				__osm_sa_slvl_create(sa, p_out_physp, p_ctxt,
						     in_port_num);
			}
		}
	}
	OSM_LOG_EXIT(sa->p_log);
}
static int discover_network_properties(lash_t * p_lash)
{
	int i, id = 0;
	uint8_t vl_min;
	osm_subn_t *p_subn = &p_lash->p_osm->subn;
	osm_switch_t *p_next_sw, *p_sw;
	osm_log_t *p_log = &p_lash->p_osm->log;

	p_lash->num_switches = cl_qmap_count(&p_subn->sw_guid_tbl);

	p_lash->switches = calloc(p_lash->num_switches, sizeof(switch_t *));
	if (!p_lash->switches)
		return -1;

	vl_min = 5;		/* set to a high value */

	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
		uint16_t port_count;
		p_sw = p_next_sw;
		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);

		p_lash->switches[id] = switch_create(p_lash, id, p_sw);
		if (!p_lash->switches[id])
			return -1;
		id++;

		port_count = osm_node_get_num_physp(p_sw->p_node);

		/* Note, ignoring port 0. management port */
		for (i = 1; i < port_count; i++) {
			osm_physp_t *p_current_physp =
			    osm_node_get_physp_ptr(p_sw->p_node, i);

			if (p_current_physp
			    && p_current_physp->p_remote_physp) {

				ib_port_info_t *p_port_info =
				    &p_current_physp->port_info;
				uint8_t port_vl_min =
				    ib_port_info_get_op_vls(p_port_info);
				if (port_vl_min && port_vl_min < vl_min)
					vl_min = port_vl_min;
			}
		}		/* for */
	}			/* while */

	vl_min = 1 << (vl_min - 1);
	if (vl_min > 15)
		vl_min = 15;

	if (p_lash->p_osm->subn.opt.lash_start_vl >= vl_min) {
		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 4D03: "
			"Start VL(%d) too high for min operational vl(%d)\n",
			p_lash->p_osm->subn.opt.lash_start_vl, vl_min);
		return -1;
	}

	p_lash->vl_min = vl_min - p_lash->p_osm->subn.opt.lash_start_vl;

	OSM_LOG(p_log, OSM_LOG_INFO,
		"min operational vl(%d) start vl(%d) max_switches(%d)\n",
		p_lash->vl_min, p_lash->p_osm->subn.opt.lash_start_vl,
		p_lash->num_switches);
	return 0;
}
Exemple #12
0
static int link_mgr_process_node(osm_sm_t * sm, IN osm_node_t * p_node,
				 IN const uint8_t link_state)
{
	osm_physp_t *p_physp, *p_physp_remote;
	uint32_t i, num_physp;
	int ret = 0;
	uint8_t current_state;

	OSM_LOG_ENTER(sm->p_log);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Node 0x%" PRIx64 " going to %s\n",
		cl_ntoh64(osm_node_get_node_guid(p_node)),
		ib_get_port_state_str(link_state));

	/*
	   Set the PortInfo for every Physical Port associated
	   with this Port.  Start iterating with port 1, since the linkstate
	   is not applicable to the management port on switches.
	 */
	num_physp = osm_node_get_num_physp(p_node);
	for (i = 0; i < num_physp; i++) {
		/*
		   Don't bother doing anything if this Physical Port is not valid.
		   or if the state of the port is already better then the
		   specified state.
		 */
		p_physp = osm_node_get_physp_ptr(p_node, (uint8_t) i);
		if (!p_physp)
			continue;

		current_state = osm_physp_get_port_state(p_physp);
		if (current_state == IB_LINK_DOWN)
			continue;

		/*
		    Set PortState to DOWN in case Remote Physical Port is
		    unreachable. We have to check this for all ports, except
		    port zero.
		 */
		p_physp_remote = osm_physp_get_remote(p_physp);
		if ((i != 0) && (!p_physp_remote ||
		    !osm_physp_is_valid(p_physp_remote))) {
			if (current_state != IB_LINK_INIT)
				link_mgr_set_physp_pi(sm, p_physp, IB_LINK_DOWN);
			continue;
		}

		/*
		   Normally we only send state update if state is lower
		   then required state. However, we need to send update if
		   no state change required.
		 */
		if (link_state != IB_LINK_NO_CHANGE &&
		    link_state <= current_state)
			OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
				"Physical port %u already %s. Skipping\n",
				p_physp->port_num,
				ib_get_port_state_str(current_state));
		else if (link_mgr_set_physp_pi(sm, p_physp, link_state))
			ret = -1;
	}

	OSM_LOG_EXIT(sm->p_log);
	return ret;
}
Exemple #13
0
static int qos_extports_setup(osm_sm_t * sm, osm_node_t *node,
			      const struct qos_config *qcfg,
			      cl_qlist_t *port_mad_list)

{
	osm_physp_t *p0, *p;
	unsigned force_update;
	unsigned num_ports = osm_node_get_num_physp(node);
	struct osm_routing_engine *re = sm->p_subn->p_osm->routing_engine_used;
	int ret = 0;
	unsigned in, out;
	uint8_t op_vl, common_op_vl = 0, max_num = 0;
	uint8_t op_vl_arr[15];

	/*
	 * Do nothing unless the most recent routing attempt was successful.
	 */
	if (!re)
		return ret;

	for (out = 1; out < num_ports; out++) {
		p = osm_node_get_physp_ptr(node, out);
		if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN)
			continue;
		force_update = p->need_update || sm->p_subn->need_update;
		p->vl_high_limit = qcfg->vl_high_limit;
		if (vlarb_update(sm, p, p->port_num, force_update, qcfg,
				 port_mad_list))
			ret = -1;
	}

	p0 = osm_node_get_physp_ptr(node, 0);
	if (!(p0->port_info.capability_mask & IB_PORT_CAP_HAS_SL_MAP))
		return ret;

	if (ib_switch_info_get_opt_sl2vlmapping(&node->sw->switch_info) &&
	    sm->p_subn->opt.use_optimized_slvl && !re->update_sl2vl) {

		/* we should find the op_vl that is used by majority of ports */
		memset(&op_vl_arr[0], 0, sizeof(op_vl_arr));
		p0 = osm_node_get_physp_ptr(node, 1);

		for (out = 1; out < num_ports; out++) {
			p = osm_node_get_physp_ptr(node, out);
			if (ib_port_info_get_port_state(&p->port_info) ==
			    IB_LINK_DOWN)
				continue;
			op_vl = ib_port_info_get_op_vls(&p->port_info);
			op_vl_arr[op_vl]++;
			if (op_vl_arr[op_vl] > max_num){
				max_num = op_vl_arr[op_vl];
				common_op_vl = op_vl;
				/* remember the port with most common op_vl */
				p0 = p;
			}

		}
		force_update = node->sw->need_update || sm->p_subn->need_update;
		if (sl2vl_update_table(sm, p0, p0->port_num, 0x30000, force_update,
					&qcfg->sl2vl, port_mad_list))
			ret = -1;
		/*
		 * Overwrite default ALL configuration if port's
		 * op_vl is different.
		 */
		for (out = 1; out < num_ports; out++) {
			p = osm_node_get_physp_ptr(node, out);
			if (ib_port_info_get_port_state(&p->port_info) ==
			    IB_LINK_DOWN)
				continue;

			force_update = p->need_update || force_update;
			if (ib_port_info_get_op_vls(&p->port_info) !=
			    common_op_vl &&
			    sl2vl_update_table(sm, p, p->port_num, 0x20000 | out,
					       force_update, &qcfg->sl2vl,
					       port_mad_list))
				ret = -1;
		}
		return ret;
	}

	/* non optimized sl2vl configuration */
	out = ib_switch_info_is_enhanced_port0(&node->sw->switch_info) ? 0 : 1;
	for (; out < num_ports; out++) {
		p = osm_node_get_physp_ptr(node, out);
		if (ib_port_info_get_port_state(&p->port_info) == IB_LINK_DOWN)
			continue;
		force_update = p->need_update || sm->p_subn->need_update;
		/* go over all in ports */
		for (in = 0; in < num_ports; in++) {
			const ib_slvl_table_t *port_sl2vl = &qcfg->sl2vl;
			ib_slvl_table_t routing_sl2vl;

			if (re->update_sl2vl) {
				routing_sl2vl = *port_sl2vl;
				re->update_sl2vl(re->context,
						 p, in, out, &routing_sl2vl);
				port_sl2vl = &routing_sl2vl;
			}
			if (sl2vl_update_table(sm, p, in, in << 8 | out,
					       force_update, port_sl2vl,
					       port_mad_list))
				ret = -1;
		}
	}

	return ret;
}
static void
__osm_sa_pkey_by_comp_mask(IN osm_sa_t * sa,
			   IN const osm_port_t * const p_port,
			   osm_pkey_search_ctxt_t * const p_ctxt)
{
	const ib_pkey_table_record_t *p_rcvd_rec;
	ib_net64_t comp_mask;
	osm_physp_t *p_physp;
	uint8_t port_num;
	uint8_t num_ports;
	const osm_physp_t *p_req_physp;

	OSM_LOG_ENTER(sa->p_log);

	p_rcvd_rec = p_ctxt->p_rcvd_rec;
	comp_mask = p_ctxt->comp_mask;
	port_num = p_rcvd_rec->port_num;
	p_req_physp = p_ctxt->p_req_physp;

	/* if this is a switch port we can search all ports
	   otherwise we must be looking on port 0 */
	if (p_port->p_node->node_info.node_type != IB_NODE_TYPE_SWITCH) {
		/* we put it in the comp mask and port num */
		port_num = p_port->p_physp->port_num;
		OSM_LOG(sa->p_log, OSM_LOG_DEBUG,
			"Using Physical Default Port Number: 0x%X (for End Node)\n",
			port_num);
		comp_mask |= IB_PKEY_COMPMASK_PORT;
	}

	if (comp_mask & IB_PKEY_COMPMASK_PORT) {
		if (port_num < osm_node_get_num_physp(p_port->p_node)) {
			p_physp =
			    osm_node_get_physp_ptr(p_port->p_node, port_num);
			/* Check that the p_physp is valid, and that is shares a pkey
			   with the p_req_physp. */
			if (p_physp &&
			    (osm_physp_share_pkey
			     (sa->p_log, p_req_physp, p_physp)))
				__osm_sa_pkey_check_physp(sa, p_physp,
							  p_ctxt);
		} else {
			OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4603: "
				"Given Physical Port Number: 0x%X is out of range should be < 0x%X\n",
				port_num,
				osm_node_get_num_physp(p_port->p_node));
			goto Exit;
		}
	} else {
		num_ports = osm_node_get_num_physp(p_port->p_node);
		for (port_num = 0; port_num < num_ports; port_num++) {
			p_physp =
			    osm_node_get_physp_ptr(p_port->p_node, port_num);
			if (!p_physp)
				continue;

			/* if the requester and the p_physp don't share a pkey -
			   continue */
			if (!osm_physp_share_pkey
			    (sa->p_log, p_req_physp, p_physp))
				continue;

			__osm_sa_pkey_check_physp(sa, p_physp, p_ctxt);
		}
	}
Exit:
	OSM_LOG_EXIT(sa->p_log);
}
Exemple #15
0
osm_signal_t osm_qos_setup(osm_opensm_t * p_osm)
{
	struct qos_config ca_config, sw0_config, swe_config, rtr_config;
	struct qos_config *cfg;
	cl_qmap_t *p_tbl;
	cl_map_item_t *p_next;
	osm_port_t *p_port;
	uint32_t num_physp;
	osm_physp_t *p_physp;
	osm_node_t *p_node;
	ib_api_status_t status;
	unsigned force_update;
	uint8_t i;

	if (!p_osm->subn.opt.qos)
		return OSM_SIGNAL_DONE;

	OSM_LOG_ENTER(&p_osm->log);

	qos_build_config(&ca_config, &p_osm->subn.opt.qos_ca_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&sw0_config, &p_osm->subn.opt.qos_sw0_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&swe_config, &p_osm->subn.opt.qos_swe_options,
			 &p_osm->subn.opt.qos_options);
	qos_build_config(&rtr_config, &p_osm->subn.opt.qos_rtr_options,
			 &p_osm->subn.opt.qos_options);

	cl_plock_excl_acquire(&p_osm->lock);

	/* read QoS policy config file */
	osm_qos_parse_policy_file(&p_osm->subn);

	p_tbl = &p_osm->subn.port_guid_tbl;
	p_next = cl_qmap_head(p_tbl);
	while (p_next != cl_qmap_end(p_tbl)) {
		p_port = (osm_port_t *) p_next;
		p_next = cl_qmap_next(p_next);

		p_node = p_port->p_node;
		if (p_node->sw) {
			num_physp = osm_node_get_num_physp(p_node);
			for (i = 1; i < num_physp; i++) {
				p_physp = osm_node_get_physp_ptr(p_node, i);
				if (!p_physp)
					continue;
				force_update = p_physp->need_update ||
				    p_osm->subn.need_update;
				status =
				    qos_physp_setup(&p_osm->log, &p_osm->sm,
						    p_port, p_physp, i,
						    force_update, &swe_config);
			}
			/* skip base port 0 */
			if (!ib_switch_info_is_enhanced_port0
			    (&p_node->sw->switch_info))
				continue;

			cfg = &sw0_config;
		} else if (osm_node_get_type(p_node) == IB_NODE_TYPE_ROUTER)
			cfg = &rtr_config;
		else
			cfg = &ca_config;

		p_physp = p_port->p_physp;
		if (!p_physp)
			continue;

		force_update = p_physp->need_update || p_osm->subn.need_update;
		status = qos_physp_setup(&p_osm->log, &p_osm->sm,
					 p_port, p_physp, 0, force_update, cfg);
	}

	cl_plock_release(&p_osm->lock);
	OSM_LOG_EXIT(&p_osm->log);

	return OSM_SIGNAL_DONE;
}
static void ucast_cache_validate(osm_ucast_mgr_t * p_mgr)
{
	cache_switch_t *p_cache_sw;
	cache_switch_t *p_remote_cache_sw;
	unsigned port_num;
	unsigned max_ports;
	uint8_t remote_node_type;
	uint16_t lid_ho;
	uint16_t remote_lid_ho;
	osm_switch_t *p_sw;
	osm_switch_t *p_remote_sw;
	osm_node_t *p_node;
	osm_physp_t *p_physp;
	osm_physp_t *p_remote_physp;
	osm_port_t *p_remote_port;
	cl_qmap_t *p_sw_tbl;

	OSM_LOG_ENTER(p_mgr->p_log);
	if (!p_mgr->cache_valid)
		goto Exit;

	/* If there are no switches in the subnet, we are done */
	p_sw_tbl = &p_mgr->p_subn->sw_guid_tbl;
	if (cl_qmap_count(p_sw_tbl) == 0) {
		osm_ucast_cache_invalidate(p_mgr);
		goto Exit;
	}

	/*
	 * Scan all the physical switch ports in the subnet.
	 * If the port need_update flag is on, check whether
	 * it's just some node/port reset or a cached topology
	 * change. Otherwise the cache is invalid.
	 */
	for (p_sw = (osm_switch_t *) cl_qmap_head(p_sw_tbl);
	     p_sw != (osm_switch_t *) cl_qmap_end(p_sw_tbl);
	     p_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item)) {

		p_node = p_sw->p_node;

		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));
		p_cache_sw = cache_get_sw(p_mgr, lid_ho);

		max_ports = osm_node_get_num_physp(p_node);

		/* skip port 0 */
		for (port_num = 1; port_num < max_ports; port_num++) {

			p_physp = osm_node_get_physp_ptr(p_node, port_num);

			if (!p_physp || !p_physp->p_remote_physp ||
			    !osm_physp_link_exists(p_physp,
						   p_physp->p_remote_physp))
				/* no valid link */
				continue;

			/*
			 * While scanning all the physical ports in the subnet,
			 * mark corresponding leaf switches in the cache.
			 */
			if (p_cache_sw &&
			    !p_cache_sw->dropped &&
			    !cache_sw_is_leaf(p_cache_sw) &&
			    p_physp->p_remote_physp->p_node &&
			    osm_node_get_type(p_physp->p_remote_physp->
					      p_node) != IB_NODE_TYPE_SWITCH)
				cache_sw_set_leaf(p_cache_sw);

			if (!p_physp->need_update)
				continue;

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Checking switch lid %u, port %u\n",
				lid_ho, port_num);

			p_remote_physp = osm_physp_get_remote(p_physp);
			remote_node_type =
			    osm_node_get_type(p_remote_physp->p_node);

			if (remote_node_type == IB_NODE_TYPE_SWITCH)
				remote_lid_ho =
				    cl_ntoh16(osm_node_get_base_lid
					      (p_remote_physp->p_node, 0));
			else
				remote_lid_ho =
				    cl_ntoh16(osm_node_get_base_lid
					      (p_remote_physp->p_node,
					       osm_physp_get_port_num
					       (p_remote_physp)));

			if (!p_cache_sw ||
			    port_num >= p_cache_sw->num_ports ||
			    !p_cache_sw->ports[port_num].remote_lid_ho) {
				/*
				 * There is some uncached change on the port.
				 * In general, the reasons might be as follows:
				 *  - switch reset
				 *  - port reset (or port down/up)
				 *  - quick connection location change
				 *  - new link (or new switch)
				 *
				 * First two reasons allow cache usage, while
				 * the last two reasons should invalidate cache.
				 *
				 * In case of quick connection location change,
				 * cache would have been invalidated by
				 * osm_ucast_cache_check_new_link() function.
				 *
				 * In case of new link between two known nodes,
				 * cache also would have been invalidated by
				 * osm_ucast_cache_check_new_link() function.
				 *
				 * Another reason is cached link between two
				 * known switches went back. In this case the
				 * osm_ucast_cache_check_new_link() function would
				 * clear both sides of the link from the cache
				 * during the discovery process, so effectively
				 * this would be equivalent to port reset.
				 *
				 * So three possible reasons remain:
				 *  - switch reset
				 *  - port reset (or port down/up)
				 *  - link of a new switch
				 *
				 * To validate cache, we need to check only the
				 * third reason - link of a new node/switch:
				 *  - If this is the local switch that is new,
				 *    then it should have (p_sw->need_update == 2).
				 *  - If the remote node is switch and it's new,
				 *    then it also should have
				 *    (p_sw->need_update == 2).
				 *  - If the remote node is CA/RTR and it's new,
				 *    then its port should have is_new flag on.
				 */
				if (p_sw->need_update == 2) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"New switch found (lid %u)\n",
						lid_ho);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				if (remote_node_type == IB_NODE_TYPE_SWITCH) {

					p_remote_sw =
					    p_remote_physp->p_node->sw;
					if (p_remote_sw->need_update == 2) {
						/* this could also be case of
						   switch coming back with an
						   additional link that it
						   didn't have before */
						OSM_LOG(p_mgr->p_log,
							OSM_LOG_DEBUG,
							"New switch/link found (lid %u)\n",
							remote_lid_ho);
						osm_ucast_cache_invalidate
						    (p_mgr);
						goto Exit;
					}
				} else {
					/*
					 * Remote node is CA/RTR.
					 * Get p_port of the remote node and
					 * check its p_port->is_new flag.
					 */
					p_remote_port =
					    osm_get_port_by_guid(p_mgr->p_subn,
								 osm_physp_get_port_guid
								 (p_remote_physp));
					if (p_remote_port->is_new) {
						OSM_LOG(p_mgr->p_log,
							OSM_LOG_DEBUG,
							"New CA/RTR found (lid %u)\n",
							remote_lid_ho);
						osm_ucast_cache_invalidate
						    (p_mgr);
						goto Exit;
					}
				}
			} else {
				/*
				 * The change on the port is cached.
				 * In general, the reasons might be as follows:
				 *  - link between two known nodes went back
				 *  - one or more nodes went back, causing all
				 *    the links to reappear
				 *
				 * If it was link that went back, then this case
				 * would have been taken care of during the
				 * discovery by osm_ucast_cache_check_new_link(),
				 * so it's some node that went back.
				 */
				if ((p_cache_sw->ports[port_num].is_leaf &&
				     remote_node_type == IB_NODE_TYPE_SWITCH) ||
				    (!p_cache_sw->ports[port_num].is_leaf &&
				     remote_node_type != IB_NODE_TYPE_SWITCH)) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"Remote node type change on switch lid %u, port %u\n",
						lid_ho, port_num);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				if (p_cache_sw->ports[port_num].remote_lid_ho !=
				    remote_lid_ho) {
					OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
						"Remote lid change on switch lid %u, port %u"
						"(was %u, now %u)\n",
						lid_ho, port_num,
						p_cache_sw->ports[port_num].
						remote_lid_ho, remote_lid_ho);
					osm_ucast_cache_invalidate(p_mgr);
					goto Exit;
				}

				/*
				 * We don't care who is the node that has
				 * reappeared in the subnet (local or remote).
				 * What's important that the cached link matches
				 * the real fabrics link.
				 * Just clean it from cache.
				 */

				p_cache_sw->ports[port_num].remote_lid_ho = 0;
				p_cache_sw->ports[port_num].is_leaf = FALSE;
				if (p_cache_sw->dropped) {
					cache_restore_ucast_info(p_mgr,
								 p_cache_sw,
								 p_sw);
					p_cache_sw->dropped = FALSE;
				}

				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Restored link from cache: lid %u, port %u to lid %u\n",
					lid_ho, port_num, remote_lid_ho);
			}
		}
	}

	/* Remove all the cached switches that
	   have all their ports restored */
	cache_cleanup_switches(p_mgr);

	/*
	 * Done scanning all the physical switch ports in the subnet.
	 * Now we need to check the other side:
	 * Scan all the cached switches and their ports:
	 *  - If the cached switch is missing in the subnet
	 *    (dropped flag is on), check that it's a leaf switch.
	 *    If it's not a leaf, the cache is invalid, because
	 *    cache can tolerate only leaf switch removal.
	 *  - If the cached switch exists in fabric, check all
	 *    its cached ports. These cached ports represent
	 *    missing link in the fabric.
	 *    The missing links that can be tolerated are:
	 *      + link to missing CA/RTR
	 *      + link to missing leaf switch
	 */
	for (p_cache_sw = (cache_switch_t *) cl_qmap_head(&p_mgr->cache_sw_tbl);
	     p_cache_sw != (cache_switch_t *) cl_qmap_end(&p_mgr->cache_sw_tbl);
	     p_cache_sw =
	     (cache_switch_t *) cl_qmap_next(&p_cache_sw->map_item)) {

		if (p_cache_sw->dropped) {
			if (!cache_sw_is_leaf(p_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Missing non-leaf switch (lid %u)\n",
					cache_sw_get_base_lid_ho(p_cache_sw));
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Missing leaf switch (lid %u) - "
				"continuing validation\n",
				cache_sw_get_base_lid_ho(p_cache_sw));
			continue;
		}

		for (port_num = 1; port_num < p_cache_sw->num_ports; port_num++) {
			if (!p_cache_sw->ports[port_num].remote_lid_ho)
				continue;

			if (p_cache_sw->ports[port_num].is_leaf) {
				CL_ASSERT(cache_sw_is_leaf(p_cache_sw));
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to CA/RTR - "
					"continuing validation\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				continue;
			}

			p_remote_cache_sw = cache_get_sw(p_mgr,
							 p_cache_sw->
							 ports[port_num].
							 remote_lid_ho);

			if (!p_remote_cache_sw || !p_remote_cache_sw->dropped) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to existing switch\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			if (!cache_sw_is_leaf(p_remote_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing link to non-leaf switch\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			/*
			 * At this point we know that the missing link is to
			 * a leaf switch. However, one case deserves a special
			 * treatment. If there was a link between two leaf
			 * switches, then missing leaf switch might break
			 * routing. It is possible that there are routes
			 * that use leaf switches to get from switch to switch
			 * and not just to get to the CAs behind the leaf switch.
			 */
			if (cache_sw_is_leaf(p_cache_sw) &&
			    cache_sw_is_leaf(p_remote_cache_sw)) {
				OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
					"Switch lid %u, port %u: missing leaf-2-leaf link\n",
					cache_sw_get_base_lid_ho(p_cache_sw),
					port_num);
				osm_ucast_cache_invalidate(p_mgr);
				goto Exit;
			}

			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Switch lid %u, port %u: missing remote leaf switch - "
				"continuing validation\n",
				cache_sw_get_base_lid_ho(p_cache_sw),
				port_num);
		}
	}

	OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG, "Unicast cache is valid\n");
	ucast_cache_dump(p_mgr);
Exit:
	OSM_LOG_EXIT(p_mgr->p_log);
}				/* osm_ucast_cache_validate() */
Exemple #17
0
static void print_node_report(cl_map_item_t * item, FILE * file, void *cxt)
{
	osm_node_t *p_node = (osm_node_t *) item;
	osm_opensm_t *osm = cxt;
	const osm_physp_t *p_physp, *p_remote_physp;
	const ib_port_info_t *p_pi;
	uint8_t port_num;
	uint32_t num_ports;
	uint8_t node_type;

	node_type = osm_node_get_type(p_node);

	num_ports = osm_node_get_num_physp(p_node);
	port_num = node_type == IB_NODE_TYPE_SWITCH ? 0 : 1;
	for (; port_num < num_ports; port_num++) {
		p_physp = osm_node_get_physp_ptr(p_node, port_num);
		if (!p_physp)
			continue;

		fprintf(file, "%-11s : %s : %02X :",
			osm_get_manufacturer_str(cl_ntoh64
						 (osm_node_get_node_guid
						  (p_node))),
			osm_get_node_type_str_fixed_width(node_type), port_num);

		p_pi = &p_physp->port_info;

		/*
		 * Port state is not defined for base switch port 0
		 */
		if (port_num == 0 &&
		    ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE)
			fprintf(file, "     :");
		else
			fprintf(file, " %s :",
				osm_get_port_state_str_fixed_width
				(ib_port_info_get_port_state(p_pi)));

		/*
		 * LID values are only meaningful in select cases.
		 */
		if (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN
		    && ((node_type == IB_NODE_TYPE_SWITCH && port_num == 0)
			|| node_type != IB_NODE_TYPE_SWITCH))
			fprintf(file, " %04X :  %01X  :",
				cl_ntoh16(p_pi->base_lid),
				ib_port_info_get_lmc(p_pi));
		else
			fprintf(file, "      :     :");

		if (port_num == 0 &&
		    ib_switch_info_is_enhanced_port0(&p_node->sw->switch_info) == FALSE)
			fprintf(file, "      :     :      ");
		else
			fprintf(file, " %s : %s : %s ",
				osm_get_mtu_str
				(ib_port_info_get_neighbor_mtu(p_pi)),
				osm_get_lwa_str(p_pi->link_width_active),
				osm_get_lsa_str
				(ib_port_info_get_link_speed_active(p_pi),
				 ib_port_info_get_link_speed_ext_active(p_pi),
				 ib_port_info_get_port_state(p_pi),
				 p_physp->ext_port_info.link_speed_active & FDR10));

		if (osm_physp_get_port_guid(p_physp) == osm->subn.sm_port_guid)
			fprintf(file, "* %016" PRIx64 " *",
				cl_ntoh64(osm_physp_get_port_guid(p_physp)));
		else
			fprintf(file, ": %016" PRIx64 " :",
				cl_ntoh64(osm_physp_get_port_guid(p_physp)));

		if (port_num
		    && (ib_port_info_get_port_state(p_pi) != IB_LINK_DOWN)) {
			p_remote_physp = osm_physp_get_remote(p_physp);
			if (p_remote_physp)
				fprintf(file, " %016" PRIx64 " (%02X)",
					cl_ntoh64(osm_physp_get_port_guid
						  (p_remote_physp)),
					osm_physp_get_port_num(p_remote_physp));
			else
				fprintf(file, " UNKNOWN");
		}

		fprintf(file, "\n");
	}

	fprintf(file, "------------------------------------------------------"
		"------------------------------------------------\n");
}
Exemple #18
0
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);
	}
}
Exemple #19
0
/**********************************************************************
 Sweeps the node 1 hop away.
 This sets off a "chain reaction" that causes discovery of the subnet.
 Used when there is suspicion that something on the subnet has changed.
**********************************************************************/
static ib_api_status_t state_mgr_sweep_hop_1(IN osm_sm_t * sm)
{
	ib_api_status_t status = IB_SUCCESS;
	osm_bind_handle_t h_bind;
	osm_madw_context_t context;
	osm_node_t *p_node;
	osm_port_t *p_port;
	osm_physp_t *p_physp;
	osm_dr_path_t *p_dr_path;
	osm_dr_path_t hop_1_path;
	ib_net64_t port_guid;
	uint8_t port_num;
	uint8_t path_array[IB_SUBNET_PATH_HOPS_MAX];
	uint8_t num_ports;
	osm_physp_t *p_ext_physp;

	OSM_LOG_ENTER(sm->p_log);

	/*
	 * First, get our own port and node objects.
	 */
	port_guid = sm->p_subn->sm_port_guid;

	CL_ASSERT(port_guid);

	/* Set the in_sweep_hop_0 flag in subn to be FALSE.
	 * This will indicate the sweeping to continue beyond the
	 * the current node.
	 * This is relevant for the case of SM on switch, since in the
	 * switch info we need to signal that the sweeping should
	 * continue through the switch. */
	sm->p_subn->in_sweep_hop_0 = FALSE;

	p_port = osm_get_port_by_guid(sm->p_subn, port_guid);
	if (!p_port) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3310: "
			"No SM port object\n");
		status = IB_ERROR;
		goto Exit;
	}

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

	port_num = ib_node_info_get_local_port_num(&p_node->node_info);

	OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
		"Probing hop 1 on local port %u\n", port_num);

	p_physp = osm_node_get_physp_ptr(p_node, port_num);

	CL_ASSERT(p_physp);

	p_dr_path = osm_physp_get_dr_path_ptr(p_physp);
	h_bind = osm_dr_path_get_bind_handle(p_dr_path);

	CL_ASSERT(h_bind != OSM_BIND_INVALID_HANDLE);

	memset(path_array, 0, sizeof(path_array));
	/* the hop_1 operations depend on the type of our node.
	 * Currently - legal nodes that can host SM are SW and CA */
	switch (osm_node_get_type(p_node)) {
	case IB_NODE_TYPE_CA:
	case IB_NODE_TYPE_ROUTER:
		memset(&context, 0, sizeof(context));
		context.ni_context.node_guid = osm_node_get_node_guid(p_node);
		context.ni_context.port_num = port_num;

		path_array[1] = port_num;

		osm_dr_path_init(&hop_1_path, h_bind, 1, path_array);
		status = osm_req_get(sm, &hop_1_path, IB_MAD_ATTR_NODE_INFO, 0,
				     CL_DISP_MSGID_NONE, &context);
		if (status != IB_SUCCESS)
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3311: "
				"Request for NodeInfo failed (%s)\n",
				ib_get_err_str(status));
		break;

	case IB_NODE_TYPE_SWITCH:
		/* Need to go over all the ports of the switch, and send a
		 * node_info from them. This doesn't include the port 0 of the
		 * switch, which hosts the SM.
		 * Note: We'll send another switchInfo on port 0, since if no
		 * ports are connected, we still want to get some response, and
		 * have the subnet come up.
		 */
		num_ports = osm_node_get_num_physp(p_node);
		for (port_num = 1; port_num < num_ports; port_num++) {
			/* go through the port only if the port is not DOWN */
			p_ext_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (p_ext_physp && ib_port_info_get_port_state
			    (&(p_ext_physp->port_info)) > IB_LINK_DOWN) {
				memset(&context, 0, sizeof(context));
				context.ni_context.node_guid =
				    osm_node_get_node_guid(p_node);
				context.ni_context.port_num = port_num;

				path_array[1] = port_num;
				osm_dr_path_init(&hop_1_path, h_bind, 1,
						 path_array);
				status = osm_req_get(sm, &hop_1_path,
						     IB_MAD_ATTR_NODE_INFO, 0,
						     CL_DISP_MSGID_NONE,
						     &context);
				if (status != IB_SUCCESS)
					OSM_LOG(sm->p_log, OSM_LOG_ERROR,
						"ERR 3312: "
						"Request for NodeInfo failed (%s)\n",
						ib_get_err_str(status));
			}
		}
		break;

	default:
		OSM_LOG(sm->p_log, OSM_LOG_ERROR,
			"ERR 3313: Unknown node type %d (%s)\n",
			osm_node_get_type(p_node), p_node->print_desc);
	}

Exit:
	OSM_LOG_EXIT(sm->p_log);
	return status;
}
static void lr_rcv_get_port_links(IN osm_sa_t * sa,
				  IN const ib_link_record_t * p_lr,
				  IN const osm_port_t * p_src_port,
				  IN const osm_port_t * p_dest_port,
				  IN const ib_net64_t comp_mask,
				  IN cl_qlist_t * p_list,
				  IN const osm_physp_t * p_req_physp)
{
	const osm_physp_t *p_src_physp;
	const osm_physp_t *p_dest_physp;
	const cl_qmap_t *p_node_tbl;
	osm_node_t *p_node;
	uint8_t port_num;
	uint8_t num_ports;
	uint8_t dest_num_ports;
	uint8_t dest_port_num;

	OSM_LOG_ENTER(sa->p_log);

	if (p_src_port) {
		if (p_dest_port) {
			/*
			   Build an LR for every link connected between both ports.
			   The inner function will discard physp combinations
			   that do not actually connect.  Don't bother screening
			   for that here.
			 */
			num_ports = osm_node_get_num_physp(p_src_port->p_node);
			dest_num_ports =
			    osm_node_get_num_physp(p_dest_port->p_node);
			for (port_num = 1; port_num < num_ports; port_num++) {
				p_src_physp =
				    osm_node_get_physp_ptr(p_src_port->p_node,
							   port_num);
				for (dest_port_num = 1;
				     dest_port_num < dest_num_ports;
				     dest_port_num++) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   dest_port_num);
					/* both physical ports should be with data */
					if (p_src_physp && p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			}
		} else {
			/*
			   Build an LR for every link connected from the source port.
			 */
			if (comp_mask & IB_LR_COMPMASK_FROM_PORT) {
				port_num = p_lr->from_port_num;
				/* If the port number is out of the range of the p_src_port, then
				   this couldn't be a relevant record. */
				if (port_num <
				    p_src_port->p_node->physp_tbl_size) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_src_port->
								   p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
			} else {
				num_ports =
				    osm_node_get_num_physp(p_src_port->p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_src_port->
								   p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
			}
		}
	} else {
		if (p_dest_port) {
			/*
			   Build an LR for every link connected to the dest port.
			 */
			if (comp_mask & IB_LR_COMPMASK_TO_PORT) {
				port_num = p_lr->to_port_num;
				/* If the port number is out of the range of the p_dest_port, then
				   this couldn't be a relevant record. */
				if (port_num <
				    p_dest_port->p_node->physp_tbl_size) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   port_num);
					if (p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, NULL,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			} else {
				num_ports =
				    osm_node_get_num_physp(p_dest_port->p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_dest_physp =
					    osm_node_get_physp_ptr(p_dest_port->
								   p_node,
								   port_num);
					if (p_dest_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, NULL,
						     p_dest_physp, comp_mask,
						     p_list, p_req_physp);
				}
			}
		} else {
			/*
			   Process the world (recurse once back into this function).
			 */
			p_node_tbl = &sa->p_subn->node_guid_tbl;
			p_node = (osm_node_t *) cl_qmap_head(p_node_tbl);

			while (p_node != (osm_node_t *) cl_qmap_end(p_node_tbl)) {
				num_ports = osm_node_get_num_physp(p_node);
				for (port_num = 1; port_num < num_ports;
				     port_num++) {
					p_src_physp =
					    osm_node_get_physp_ptr(p_node,
								   port_num);
					if (p_src_physp)
						lr_rcv_get_physp_link
						    (sa, p_lr, p_src_physp,
						     NULL, comp_mask, p_list,
						     p_req_physp);
				}
				p_node = (osm_node_t *) cl_qmap_next(&p_node->
								     map_item);
			}
		}
	}

	OSM_LOG_EXIT(sa->p_log);
}
void osm_ucast_cache_add_node(osm_ucast_mgr_t * p_mgr, osm_node_t * p_node)
{
	uint16_t lid_ho;
	uint8_t max_ports;
	uint8_t port_num;
	osm_physp_t *p_physp;
	cache_switch_t *p_cache_sw;

	OSM_LOG_ENTER(p_mgr->p_log);

	if (!p_mgr->cache_valid)
		goto Exit;

	if (osm_node_get_type(p_node) == IB_NODE_TYPE_SWITCH) {

		lid_ho = cl_ntoh16(osm_node_get_base_lid(p_node, 0));

		if (!lid_ho) {
			OSM_LOG(p_mgr->p_log, OSM_LOG_VERBOSE,
				"Skip caching. Switch dropped before "
				"it gets a valid lid.\n");
			osm_ucast_cache_invalidate(p_mgr);
			goto Exit;
		}

		OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
			"Caching dropped switch lid %u\n", lid_ho);

		if (!p_node->sw) {
			/* something is wrong - forget about cache */
			OSM_LOG(p_mgr->p_log, OSM_LOG_ERROR,
				"ERR AD03: no switch info for node lid %u - "
				"clearing cache\n", lid_ho);
			osm_ucast_cache_invalidate(p_mgr);
			goto Exit;
		}

		/* unlink (add to cache) all the ports of this switch */
		max_ports = osm_node_get_num_physp(p_node);
		for (port_num = 1; port_num < max_ports; port_num++) {

			p_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (!p_physp || !p_physp->p_remote_physp)
				continue;

			osm_ucast_cache_add_link(p_mgr, p_physp,
						 p_physp->p_remote_physp);
		}

		/*
		 * All the ports have been dropped (cached).
		 * If one of the ports was connected to CA/RTR,
		 * then the cached switch would be marked as leaf.
		 * If it isn't, then the dropped switch isn't a leaf,
		 * and cache can't handle it.
		 */

		p_cache_sw = cache_get_sw(p_mgr, lid_ho);

		/* p_cache_sw could be NULL if it has no remote phys ports */
		if (!p_cache_sw || !cache_sw_is_leaf(p_cache_sw)) {
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"Dropped non-leaf switch (lid %u)\n", lid_ho);
			osm_ucast_cache_invalidate(p_mgr);
			goto Exit;
		}

		p_cache_sw->dropped = TRUE;

		if (!p_node->sw->num_hops || !p_node->sw->hops) {
			OSM_LOG(p_mgr->p_log, OSM_LOG_DEBUG,
				"No LID matrices for switch lid %u\n", lid_ho);
			osm_ucast_cache_invalidate(p_mgr);
			goto Exit;
		}

		/* lid matrices */

		p_cache_sw->num_hops = p_node->sw->num_hops;
		p_node->sw->num_hops = 0;
		p_cache_sw->hops = p_node->sw->hops;
		p_node->sw->hops = NULL;

		/* linear forwarding table */

		if (p_node->sw->new_lft) {
			/* LFT buffer exists - we use it, because
			   it is more updated than the switch's LFT */
			p_cache_sw->lft = p_node->sw->new_lft;
			p_node->sw->new_lft = NULL;
		} else {
			/* no LFT buffer, so we use the switch's LFT */
			p_cache_sw->lft = p_node->sw->lft;
			p_node->sw->lft = NULL;
			p_node->sw->lft_size = 0;
		}
		p_cache_sw->max_lid_ho = p_node->sw->max_lid_ho;
	} else {
		/* dropping CA/RTR: add to cache all the ports of this node */
		max_ports = osm_node_get_num_physp(p_node);
		for (port_num = 1; port_num < max_ports; port_num++) {

			p_physp = osm_node_get_physp_ptr(p_node, port_num);
			if (!p_physp || !p_physp->p_remote_physp)
				continue;

			CL_ASSERT(osm_node_get_type
				  (p_physp->p_remote_physp->p_node) ==
				  IB_NODE_TYPE_SWITCH);

			osm_ucast_cache_add_link(p_mgr,
						 p_physp->p_remote_physp,
						 p_physp);
		}
	}
Exit:
	OSM_LOG_EXIT(p_mgr->p_log);
}				/* osm_ucast_cache_add_node() */