예제 #1
0
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void ni_rcv_get_node_desc(IN osm_sm_t * sm, IN osm_node_t * p_node,
				 IN const osm_madw_t * p_madw)
{
	ib_node_info_t *p_ni;
	ib_smp_t *p_smp;
	uint8_t port_num;
	osm_physp_t *p_physp = NULL;

	OSM_LOG_ENTER(sm->p_log);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_ni = ib_smp_get_payload_ptr(p_smp);
	port_num = ib_node_info_get_local_port_num(p_ni);

	/*
	   Request PortInfo & NodeDescription attributes for the port
	   that responded to the NodeInfo attribute.
	   Because this is a channel adapter or router, we are
	   not allowed to request PortInfo for the other ports.
	   Set the context union properly, so the recipient
	   knows which node & port are relevant.
	 */
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
	if (!p_physp) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR OD1F: "
			"Failed to find physp for port %d of Node GUID 0x%"
			PRIx64 "\n", port_num,
			cl_ntoh64(osm_node_get_node_guid(p_node)));
		return;
	}

	osm_req_get_node_desc(sm, p_physp);

	OSM_LOG_EXIT(sm->p_log);
}
예제 #2
0
osm_node_t *osm_node_new(IN const osm_madw_t * p_madw)
{
	osm_node_t *p_node;
	ib_smp_t *p_smp;
	ib_node_info_t *p_ni;
	uint8_t i;
	uint32_t size;

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_ni = ib_smp_get_payload_ptr(p_smp);

	/*
	   The node object already contains one physical port object.
	   Therefore, subtract 1 from the number of physical ports
	   used by the switch.  This is not done for CA's since they
	   need to occupy 1 more physp than they physically have since
	   we still reserve room for a "port 0".
	 */
	size = p_ni->num_ports;

	p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
	if (!p_node)
		return NULL;

	memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
	p_node->node_info = *p_ni;
	p_node->physp_tbl_size = size + 1;

	p_node->physp_discovered = malloc(sizeof(uint8_t) * p_node->physp_tbl_size);
	if (!p_node->physp_discovered) {
		free(p_node);
		return NULL;
	}
	memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size);
	/*
	   Construct Physical Port objects owned by this Node.
	   Then, initialize the Physical Port through with we
	   discovered this port.
	   For switches, all ports have the same GUID.
	   For CAs and routers, each port has a different GUID, so we only
	   know the GUID for the port that responded to our
	   Get(NodeInfo).
	 */
	for (i = 0; i < p_node->physp_tbl_size; i++)
		osm_physp_construct(&p_node->physp_table[i]);

	if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
		for (i = 0; i <= p_ni->num_ports; i++)
			osm_node_init_physp(p_node, i, p_madw);
	else
		osm_node_init_physp(p_node,
				    ib_node_info_get_local_port_num(p_ni),
				    p_madw);
	p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);

	return p_node;
}
예제 #3
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));
	}
}
예제 #4
0
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void ni_rcv_process_existing(IN osm_sm_t * sm, IN osm_node_t * p_node,
				    IN const osm_madw_t * p_madw)
{
	ib_node_info_t *p_ni;
	ib_smp_t *p_smp;
	osm_ni_context_t *p_ni_context;
	uint8_t port_num;

	OSM_LOG_ENTER(sm->p_log);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_ni = ib_smp_get_payload_ptr(p_smp);
	p_ni_context = osm_madw_get_ni_context_ptr(p_madw);
	port_num = ib_node_info_get_local_port_num(p_ni);

	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
		"Rediscovered %s node 0x%" PRIx64 " TID 0x%" PRIx64
		", discovered %u times already\n",
		ib_get_node_type_str(p_ni->node_type),
		cl_ntoh64(p_ni->node_guid),
		cl_ntoh64(p_smp->trans_id), p_node->discovery_count);

	if (PF(port_num > p_ni->num_ports)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0C: "
			"Existing %s node GUID 0x%" PRIx64 "is non-compliant "
			"and is being ignored since the "
			"local port num %u > num ports %u\n",
			ib_get_node_type_str(p_ni->node_type),
			cl_ntoh64(p_ni->node_guid), port_num,
			p_ni->num_ports);
		goto Exit;
	}

	/*
	   If we haven't already encountered this existing node
	   on this particular sweep, then process further.
	 */
	p_node->discovery_count++;

	switch (p_ni->node_type) {
	case IB_NODE_TYPE_CA:
	case IB_NODE_TYPE_ROUTER:
		ni_rcv_process_existing_ca_or_router(sm, p_node, p_madw);
		break;

	case IB_NODE_TYPE_SWITCH:
		ni_rcv_process_existing_switch(sm, p_node, p_madw);
		break;

	default:
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D09: "
			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
		break;
	}

	if ( p_ni->sys_guid != p_node->node_info.sys_guid) {
		OSM_LOG(sm->p_log, OSM_LOG_DEBUG, "Updated SysImageGUID: 0x%"
			PRIx64 " for node 0x%" PRIx64 "\n",
			cl_ntoh64(p_ni->sys_guid),
			cl_ntoh64(p_ni->node_guid));
	}
	ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
	p_node->node_info = *p_ni;

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
예제 #5
0
/**********************************************************************
 The plock must NOT be held before calling this function.
**********************************************************************/
static void ni_rcv_process_new(IN osm_sm_t * sm, IN const osm_madw_t * p_madw)
{
	osm_node_t *p_node;
	osm_node_t *p_node_check;
	osm_port_t *p_port;
	osm_port_t *p_port_check;
	osm_router_t *p_rtr = NULL;
	osm_router_t *p_rtr_check;
	cl_qmap_t *p_rtr_guid_tbl;
	ib_node_info_t *p_ni;
	ib_smp_t *p_smp;
	osm_ni_context_t *p_ni_context;
	osm_alias_guid_t *p_alias_guid, *p_alias_guid_check;
	uint8_t port_num;

	OSM_LOG_ENTER(sm->p_log);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_ni = ib_smp_get_payload_ptr(p_smp);
	p_ni_context = osm_madw_get_ni_context_ptr(p_madw);
	port_num = ib_node_info_get_local_port_num(p_ni);

	osm_dump_smp_dr_path_v2(sm->p_log, p_smp, FILE_ID, OSM_LOG_VERBOSE);

	OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
		"Discovered new %s node,"
		"\n\t\t\t\tGUID 0x%" PRIx64 ", TID 0x%" PRIx64 "\n",
		ib_get_node_type_str(p_ni->node_type),
		cl_ntoh64(p_ni->node_guid), cl_ntoh64(p_smp->trans_id));

	if (PF(port_num > p_ni->num_ports)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D0A: "
			"New %s node GUID 0x%" PRIx64 "is non-compliant and "
			"is being ignored since the "
			"local port num %u > num ports %u\n",
			ib_get_node_type_str(p_ni->node_type),
			cl_ntoh64(p_ni->node_guid), port_num,
			p_ni->num_ports);
		goto Exit;
	}

	p_node = osm_node_new(p_madw);
	if (PF(p_node == NULL)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D07: "
			"Unable to create new node object\n");
		goto Exit;
	}

	/*
	   Create a new port object to represent this node's physical
	   ports in the port table.
	 */
	p_port = osm_port_new(p_ni, p_node);
	if (PF(p_port == NULL)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D14: "
			"Unable to create new port object\n");
		osm_node_delete(&p_node);
		goto Exit;
	}

	/*
	   Add the new port object to the database.
	 */
	p_port_check =
	    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
					  p_ni->port_guid, &p_port->map_item);
	if (PF(p_port_check != p_port)) {
		/*
		   We should never be here!
		   Somehow, this port GUID already exists in the table.
		 */
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D15: "
			"Duplicate Port GUID 0x%" PRIx64
			"! Found by the two directed routes:\n",
			cl_ntoh64(p_ni->port_guid));
		osm_dump_dr_path_v2(sm->p_log,
				    osm_physp_get_dr_path_ptr(p_port->p_physp),
				    FILE_ID, OSM_LOG_ERROR);
		osm_dump_dr_path_v2(sm->p_log,
				    osm_physp_get_dr_path_ptr(p_port_check->
							   p_physp),
				    FILE_ID, OSM_LOG_ERROR);
		osm_port_delete(&p_port);
		osm_node_delete(&p_node);
		goto Exit;
	}

	p_alias_guid = osm_alias_guid_new(p_ni->port_guid,
					  p_port);
	if (PF(!p_alias_guid)) {
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D18: "
			"alias guid memory allocation failed"
			" for port GUID 0x%" PRIx64 "\n",
			cl_ntoh64(p_ni->port_guid));
		goto alias_done2;
	}

	/* insert into alias guid table */
	p_alias_guid_check =
		(osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl,
						    p_alias_guid->alias_guid,
						    &p_alias_guid->map_item);
	if (p_alias_guid_check != p_alias_guid) {
		/* alias GUID is a duplicate */
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D19: "
			"Duplicate alias port GUID 0x%" PRIx64 "\n",
			cl_ntoh64(p_ni->port_guid));
		osm_alias_guid_delete(&p_alias_guid);
	}

alias_done2:
	/* If we are a master, then this means the port is new on the subnet.
	   Mark it as new - need to send trap 64 on these ports.
	   The condition that we are master is true, since if we are in discovering
	   state (meaning we woke up from standby or we are just initializing),
	   then these ports may be new to us, but are not new on the subnet.
	   If we are master, then the subnet as we know it is the updated one,
	   and any new ports we encounter should cause trap 64. C14-72.1.1 */
	if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
		p_port->is_new = 1;

	/* If there were RouterInfo or other router attribute,
	   this would be elsewhere */
	if (p_ni->node_type == IB_NODE_TYPE_ROUTER) {
		if (PF((p_rtr = osm_router_new(p_port)) == NULL))
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1A: "
				"Unable to create new router object\n");
		else {
			p_rtr_guid_tbl = &sm->p_subn->rtr_guid_tbl;
			p_rtr_check =
			    (osm_router_t *) cl_qmap_insert(p_rtr_guid_tbl,
							    p_ni->port_guid,
							    &p_rtr->map_item);
			if (PF(p_rtr_check != p_rtr))
				OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1B: "
					"Unable to add port GUID:0x%016" PRIx64
					" to router table\n",
					cl_ntoh64(p_ni->port_guid));
		}
	}

	p_node_check =
	    (osm_node_t *) cl_qmap_insert(&sm->p_subn->node_guid_tbl,
					  p_ni->node_guid, &p_node->map_item);
	if (PF(p_node_check != p_node)) {
		/*
		   This node must have been inserted by another thread.
		   This is unexpected, but is not an error.
		   We can simply clean-up, since the other thread will
		   see this processing through to completion.
		 */
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Discovery race detected at node 0x%" PRIx64 "\n",
			cl_ntoh64(p_ni->node_guid));
		osm_node_delete(&p_node);
		p_node = p_node_check;
		ni_rcv_set_links(sm, p_node, port_num, p_ni_context);
		goto Exit;
	} else
		ni_rcv_set_links(sm, p_node, port_num, p_ni_context);

	p_node->discovery_count++;
	ni_rcv_get_node_desc(sm, p_node, p_madw);

	switch (p_ni->node_type) {
	case IB_NODE_TYPE_CA:
	case IB_NODE_TYPE_ROUTER:
		ni_rcv_process_new_ca_or_router(sm, p_node, p_madw);
		break;
	case IB_NODE_TYPE_SWITCH:
		ni_rcv_process_new_switch(sm, p_node, p_madw);
		break;
	default:
		OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D16: "
			"Unknown node type %u with GUID 0x%" PRIx64 "\n",
			p_ni->node_type, cl_ntoh64(p_ni->node_guid));
		break;
	}

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
예제 #6
0
/**********************************************************************
 The plock must be held before calling this function.
**********************************************************************/
static void ni_rcv_process_existing_ca_or_router(IN osm_sm_t * sm,
						 IN osm_node_t * p_node,
						 IN const osm_madw_t * p_madw)
{
	ib_node_info_t *p_ni;
	ib_smp_t *p_smp;
	osm_port_t *p_port;
	osm_port_t *p_port_check;
	uint8_t port_num;
	osm_dr_path_t *p_dr_path;
	osm_alias_guid_t *p_alias_guid, *p_alias_guid_check;

	OSM_LOG_ENTER(sm->p_log);

	p_smp = osm_madw_get_smp_ptr(p_madw);
	p_ni = ib_smp_get_payload_ptr(p_smp);
	port_num = ib_node_info_get_local_port_num(p_ni);

	/*
	   Determine if we have encountered this node through a
	   previously undiscovered port.  If so, build the new
	   port object.
	 */
	p_port = osm_get_port_by_guid(sm->p_subn, p_ni->port_guid);
	if (!p_port) {
		OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
			"Creating new port object with GUID 0x%" PRIx64 "\n",
			cl_ntoh64(p_ni->port_guid));

		osm_node_init_physp(p_node, port_num, p_madw);

		p_port = osm_port_new(p_ni, p_node);
		if (PF(p_port == NULL)) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D04: "
				"Unable to create new port object\n");
			goto Exit;
		}

		/*
		   Add the new port object to the database.
		 */
		p_port_check =
		    (osm_port_t *) cl_qmap_insert(&sm->p_subn->port_guid_tbl,
						  p_ni->port_guid,
						  &p_port->map_item);
		if (PF(p_port_check != p_port)) {
			/*
			   We should never be here!
			   Somehow, this port GUID already exists in the table.
			 */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D12: "
				"Port 0x%" PRIx64 " already in the database!\n",
				cl_ntoh64(p_ni->port_guid));

			osm_port_delete(&p_port);
			goto Exit;
		}

		p_alias_guid = osm_alias_guid_new(p_ni->port_guid,
						  p_port);
		if (PF(!p_alias_guid)) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D11: "
				"alias guid memory allocation failed"
				" for port GUID 0x%" PRIx64 "\n",
				cl_ntoh64(p_ni->port_guid));
			goto alias_done;
		}

		/* insert into alias guid table */
		p_alias_guid_check =
			(osm_alias_guid_t *) cl_qmap_insert(&sm->p_subn->alias_port_guid_tbl,
							    p_alias_guid->alias_guid,
							    &p_alias_guid->map_item);
		if (p_alias_guid_check != p_alias_guid) {
			/* alias GUID is a duplicate */
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D13: "
				"Duplicate alias port GUID 0x%" PRIx64 "\n",
				cl_ntoh64(p_ni->port_guid));
			osm_alias_guid_delete(&p_alias_guid);
			osm_port_delete(&p_port);
			goto Exit;
		}

alias_done:
		/* If we are a master, then this means the port is new on the subnet.
		   Mark it as new - need to send trap 64 for these ports.
		   The condition that we are master is true, since if we are in discovering
		   state (meaning we woke up from standby or we are just initializing),
		   then these ports may be new to us, but are not new on the subnet.
		   If we are master, then the subnet as we know it is the updated one,
		   and any new ports we encounter should cause trap 64. C14-72.1.1 */
		if (sm->p_subn->sm_state == IB_SMINFO_STATE_MASTER)
			p_port->is_new = 1;

	} else {
		osm_physp_t *p_physp = osm_node_get_physp_ptr(p_node, port_num);

		if (PF(p_physp == NULL)) {
			OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 0D1C: "
				"No physical port found for node GUID 0x%"
				PRIx64 " port %u. Might be duplicate port GUID\n",
				cl_ntoh64(p_node->node_info.node_guid),
				port_num);
			goto Exit;
		}

		/*
		   Update the DR Path to the port,
		   in case the old one is no longer available.
		 */
		p_dr_path = osm_physp_get_dr_path_ptr(p_physp);

		osm_dr_path_init(p_dr_path, p_smp->hop_count,
				 p_smp->initial_path);
	}

	ni_rcv_get_port_info(sm, p_node, p_madw);

Exit:
	OSM_LOG_EXIT(sm->p_log);
}
예제 #7
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;
}