Blame opensm/osm_node.c

Packit 13e616
/*
Packit 13e616
 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
Packit 13e616
 * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
Packit 13e616
 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
Packit 13e616
 *
Packit 13e616
 * This software is available to you under a choice of one of two
Packit 13e616
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit 13e616
 * General Public License (GPL) Version 2, available from the file
Packit 13e616
 * COPYING in the main directory of this source tree, or the
Packit 13e616
 * OpenIB.org BSD license below:
Packit 13e616
 *
Packit 13e616
 *     Redistribution and use in source and binary forms, with or
Packit 13e616
 *     without modification, are permitted provided that the following
Packit 13e616
 *     conditions are met:
Packit 13e616
 *
Packit 13e616
 *      - Redistributions of source code must retain the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer.
Packit 13e616
 *
Packit 13e616
 *      - Redistributions in binary form must reproduce the above
Packit 13e616
 *        copyright notice, this list of conditions and the following
Packit 13e616
 *        disclaimer in the documentation and/or other materials
Packit 13e616
 *        provided with the distribution.
Packit 13e616
 *
Packit 13e616
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit 13e616
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit 13e616
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit 13e616
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit 13e616
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit 13e616
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit 13e616
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit 13e616
 * SOFTWARE.
Packit 13e616
 *
Packit 13e616
 */
Packit 13e616
Packit 13e616
/*
Packit 13e616
 * Abstract:
Packit 13e616
 *    Implementation of osm_node_t.
Packit 13e616
 * This object represents an Infiniband Node.
Packit 13e616
 * This object is part of the opensm family of objects.
Packit 13e616
 */
Packit 13e616
Packit 13e616
#if HAVE_CONFIG_H
Packit 13e616
#  include <config.h>
Packit 13e616
#endif				/* HAVE_CONFIG_H */
Packit 13e616
Packit 13e616
#include <stdlib.h>
Packit 13e616
#include <iba/ib_types.h>
Packit 13e616
#include <opensm/osm_file_ids.h>
Packit 13e616
#define FILE_ID OSM_FILE_NODE_C
Packit 13e616
#include <opensm/osm_node.h>
Packit 13e616
#include <opensm/osm_madw.h>
Packit 13e616
Packit 13e616
void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num,
Packit 13e616
			 IN const osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	ib_net64_t port_guid;
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	ib_node_info_t *p_ni;
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
Packit 13e616
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit 13e616
	port_guid = p_ni->port_guid;
Packit 13e616
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
Packit 13e616
	osm_physp_init(&p_node->physp_table[port_num],
Packit 13e616
		       port_guid, port_num, p_node,
Packit 13e616
		       osm_madw_get_bind_handle(p_madw),
Packit 13e616
		       p_smp->hop_count, p_smp->initial_path);
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_node_t *osm_node_new(IN const osm_madw_t * p_madw)
Packit 13e616
{
Packit 13e616
	osm_node_t *p_node;
Packit 13e616
	ib_smp_t *p_smp;
Packit 13e616
	ib_node_info_t *p_ni;
Packit 13e616
	uint8_t i;
Packit 13e616
	uint32_t size;
Packit 13e616
Packit 13e616
	p_smp = osm_madw_get_smp_ptr(p_madw);
Packit 13e616
	p_ni = ib_smp_get_payload_ptr(p_smp);
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   The node object already contains one physical port object.
Packit 13e616
	   Therefore, subtract 1 from the number of physical ports
Packit 13e616
	   used by the switch.  This is not done for CA's since they
Packit 13e616
	   need to occupy 1 more physp than they physically have since
Packit 13e616
	   we still reserve room for a "port 0".
Packit 13e616
	 */
Packit 13e616
	size = p_ni->num_ports;
Packit 13e616
Packit 13e616
	p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
Packit 13e616
	if (!p_node)
Packit 13e616
		return NULL;
Packit 13e616
Packit 13e616
	memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
Packit 13e616
	p_node->node_info = *p_ni;
Packit 13e616
	p_node->physp_tbl_size = size + 1;
Packit 13e616
Packit 13e616
	p_node->physp_discovered = malloc(sizeof(uint8_t) * p_node->physp_tbl_size);
Packit 13e616
	if (!p_node->physp_discovered) {
Packit 13e616
		free(p_node);
Packit 13e616
		return NULL;
Packit 13e616
	}
Packit 13e616
	memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size);
Packit 13e616
	/*
Packit 13e616
	   Construct Physical Port objects owned by this Node.
Packit 13e616
	   Then, initialize the Physical Port through with we
Packit 13e616
	   discovered this port.
Packit 13e616
	   For switches, all ports have the same GUID.
Packit 13e616
	   For CAs and routers, each port has a different GUID, so we only
Packit 13e616
	   know the GUID for the port that responded to our
Packit 13e616
	   Get(NodeInfo).
Packit 13e616
	 */
Packit 13e616
	for (i = 0; i < p_node->physp_tbl_size; i++)
Packit 13e616
		osm_physp_construct(&p_node->physp_table[i]);
Packit 13e616
Packit 13e616
	if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
Packit 13e616
		for (i = 0; i <= p_ni->num_ports; i++)
Packit 13e616
			osm_node_init_physp(p_node, i, p_madw);
Packit 13e616
	else
Packit 13e616
		osm_node_init_physp(p_node,
Packit 13e616
				    ib_node_info_get_local_port_num(p_ni),
Packit 13e616
				    p_madw);
Packit 13e616
	p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
Packit 13e616
Packit 13e616
	return p_node;
Packit 13e616
}
Packit 13e616
Packit 13e616
static void node_destroy(IN osm_node_t * p_node)
Packit 13e616
{
Packit 13e616
	uint16_t i;
Packit 13e616
Packit 13e616
	/*
Packit 13e616
	   Cleanup all physports
Packit 13e616
	 */
Packit 13e616
	for (i = 0; i < p_node->physp_tbl_size; i++)
Packit 13e616
		osm_physp_destroy(&p_node->physp_table[i]);
Packit 13e616
Packit 13e616
	/* cleanup printable node_desc field */
Packit 13e616
	if (p_node->print_desc)
Packit 13e616
		free(p_node->print_desc);
Packit 13e616
Packit 13e616
	/* cleanup physp_discovered array */
Packit 13e616
	free(p_node->physp_discovered);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_node_delete(IN OUT osm_node_t ** p_node)
Packit 13e616
{
Packit 13e616
	CL_ASSERT(p_node && *p_node);
Packit 13e616
	node_destroy(*p_node);
Packit 13e616
	free(*p_node);
Packit 13e616
	*p_node = NULL;
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num,
Packit 13e616
		   IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
	p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
Packit 13e616
Packit 13e616
	if (p_physp->p_remote_physp)
Packit 13e616
		p_physp->p_remote_physp->p_remote_physp = NULL;
Packit 13e616
	if (p_remote_physp->p_remote_physp)
Packit 13e616
		p_remote_physp->p_remote_physp->p_remote_physp = NULL;
Packit 13e616
Packit 13e616
	osm_physp_link(p_physp, p_remote_physp);
Packit 13e616
}
Packit 13e616
Packit 13e616
void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num,
Packit 13e616
		     IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
Packit 13e616
Packit 13e616
	if (osm_node_link_exists(p_node, port_num,
Packit 13e616
				 p_remote_node, remote_port_num)) {
Packit 13e616
Packit 13e616
		p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
		p_remote_physp =
Packit 13e616
		    osm_node_get_physp_ptr(p_remote_node, remote_port_num);
Packit 13e616
Packit 13e616
		osm_physp_unlink(p_physp, p_remote_physp);
Packit 13e616
	}
Packit 13e616
}
Packit 13e616
Packit 13e616
boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num,
Packit 13e616
			       IN osm_node_t * p_remote_node,
Packit 13e616
			       IN uint8_t remote_port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
Packit 13e616
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
	p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
Packit 13e616
Packit 13e616
	return osm_physp_link_exists(p_physp, p_remote_physp);
Packit 13e616
}
Packit 13e616
Packit 13e616
boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node,
Packit 13e616
					IN uint8_t port_num,
Packit 13e616
					IN osm_node_t * p_remote_node,
Packit 13e616
					IN uint8_t remote_port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
Packit 13e616
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
	p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
Packit 13e616
Packit 13e616
	return (p_physp && p_remote_physp);
Packit 13e616
}
Packit 13e616
Packit 13e616
boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
	return osm_physp_has_any_link(p_physp);
Packit 13e616
}
Packit 13e616
Packit 13e616
osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node,
Packit 13e616
				     IN uint8_t port_num,
Packit 13e616
				     OUT uint8_t * p_remote_port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
Packit 13e616
	if (!p_physp || !osm_physp_has_any_link(p_physp))
Packit 13e616
		return NULL;
Packit 13e616
Packit 13e616
	p_remote_physp = osm_physp_get_remote(p_physp);
Packit 13e616
	if (p_remote_port_num)
Packit 13e616
		*p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
Packit 13e616
Packit 13e616
	return osm_physp_get_node_ptr(p_remote_physp);
Packit 13e616
}
Packit 13e616
Packit 13e616
/**********************************************************************
Packit 13e616
 The lock must be held before calling this function.
Packit 13e616
**********************************************************************/
Packit 13e616
ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node,
Packit 13e616
					IN uint32_t port_num)
Packit 13e616
{
Packit 13e616
	osm_physp_t *p_physp;
Packit 13e616
	osm_physp_t *p_remote_physp;
Packit 13e616
	CL_ASSERT(port_num < p_node->physp_tbl_size);
Packit 13e616
Packit 13e616
	p_physp = osm_node_get_physp_ptr(p_node, port_num);
Packit 13e616
	if (p_physp) {
Packit 13e616
		p_remote_physp = osm_physp_get_remote(p_physp);
Packit 13e616
		return osm_physp_get_base_lid(p_remote_physp);
Packit 13e616
	}
Packit 13e616
Packit 13e616
	return 0;
Packit 13e616
}