1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of osm_node_t. 39219820Sjeff * This object represents an Infiniband Node. 40219820Sjeff * This object is part of the opensm family of objects. 41219820Sjeff */ 42219820Sjeff 43219820Sjeff#if HAVE_CONFIG_H 44219820Sjeff# include <config.h> 45219820Sjeff#endif /* HAVE_CONFIG_H */ 46219820Sjeff 47219820Sjeff#include <stdlib.h> 48219820Sjeff#include <iba/ib_types.h> 49219820Sjeff#include <opensm/osm_node.h> 50219820Sjeff#include <opensm/osm_madw.h> 51219820Sjeff 52219820Sjeff/********************************************************************** 53219820Sjeff **********************************************************************/ 54219820Sjeffvoid 55219820Sjeffosm_node_init_physp(IN osm_node_t * const p_node, 56219820Sjeff IN const osm_madw_t * const p_madw) 57219820Sjeff{ 58219820Sjeff ib_net64_t port_guid; 59219820Sjeff ib_smp_t *p_smp; 60219820Sjeff ib_node_info_t *p_ni; 61219820Sjeff uint8_t port_num; 62219820Sjeff 63219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 64219820Sjeff 65219820Sjeff p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp); 66219820Sjeff port_guid = p_ni->port_guid; 67219820Sjeff port_num = ib_node_info_get_local_port_num(p_ni); 68219820Sjeff 69219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 70219820Sjeff 71219820Sjeff osm_physp_init(&p_node->physp_table[port_num], 72219820Sjeff port_guid, port_num, p_node, 73219820Sjeff osm_madw_get_bind_handle(p_madw), 74219820Sjeff p_smp->hop_count, p_smp->initial_path); 75219820Sjeff} 76219820Sjeff 77219820Sjeff/********************************************************************** 78219820Sjeff **********************************************************************/ 79219820Sjeffstatic void node_init_physp0(IN osm_node_t * const p_node, 80219820Sjeff IN const osm_madw_t * const p_madw) 81219820Sjeff{ 82219820Sjeff ib_smp_t *p_smp; 83219820Sjeff ib_node_info_t *p_ni; 84219820Sjeff 85219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 86219820Sjeff p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp); 87219820Sjeff 88219820Sjeff osm_physp_init(&p_node->physp_table[0], 89219820Sjeff p_ni->port_guid, 0, p_node, 90219820Sjeff osm_madw_get_bind_handle(p_madw), 91219820Sjeff p_smp->hop_count, p_smp->initial_path); 92219820Sjeff} 93219820Sjeff 94219820Sjeff/********************************************************************** 95219820Sjeff **********************************************************************/ 96219820Sjeffosm_node_t *osm_node_new(IN const osm_madw_t * const p_madw) 97219820Sjeff{ 98219820Sjeff osm_node_t *p_node; 99219820Sjeff ib_smp_t *p_smp; 100219820Sjeff ib_node_info_t *p_ni; 101219820Sjeff uint8_t i; 102219820Sjeff uint32_t size; 103219820Sjeff 104219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 105219820Sjeff p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp); 106219820Sjeff 107219820Sjeff /* 108219820Sjeff The node object already contains one physical port object. 109219820Sjeff Therefore, subtract 1 from the number of physical ports 110219820Sjeff used by the switch. This is not done for CA's since they 111219820Sjeff need to occupy 1 more physp than they physically have since 112219820Sjeff we still reserve room for a "port 0". 113219820Sjeff */ 114219820Sjeff size = p_ni->num_ports; 115219820Sjeff 116219820Sjeff p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size); 117219820Sjeff if (!p_node) 118219820Sjeff return NULL; 119219820Sjeff 120219820Sjeff memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size); 121219820Sjeff p_node->node_info = *p_ni; 122219820Sjeff p_node->physp_tbl_size = size + 1; 123219820Sjeff 124219820Sjeff /* 125219820Sjeff Construct Physical Port objects owned by this Node. 126219820Sjeff Then, initialize the Physical Port through with we 127219820Sjeff discovered this port. 128219820Sjeff For switches, all ports have the same GUID. 129219820Sjeff For CAs and routers, each port has a different GUID, so we only 130219820Sjeff know the GUID for the port that responded to our 131219820Sjeff Get(NodeInfo). 132219820Sjeff */ 133219820Sjeff for (i = 0; i < p_node->physp_tbl_size; i++) 134219820Sjeff osm_physp_construct(&p_node->physp_table[i]); 135219820Sjeff 136219820Sjeff osm_node_init_physp(p_node, p_madw); 137219820Sjeff if (p_ni->node_type == IB_NODE_TYPE_SWITCH) 138219820Sjeff node_init_physp0(p_node, p_madw); 139219820Sjeff p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN); 140219820Sjeff 141219820Sjeff return (p_node); 142219820Sjeff} 143219820Sjeff 144219820Sjeff/********************************************************************** 145219820Sjeff **********************************************************************/ 146219820Sjeffstatic void osm_node_destroy(IN osm_node_t * p_node) 147219820Sjeff{ 148219820Sjeff uint16_t i; 149219820Sjeff 150219820Sjeff /* 151219820Sjeff Cleanup all physports 152219820Sjeff */ 153219820Sjeff for (i = 0; i < p_node->physp_tbl_size; i++) 154219820Sjeff osm_physp_destroy(&p_node->physp_table[i]); 155219820Sjeff 156219820Sjeff /* cleanup printable node_desc field */ 157219820Sjeff if (p_node->print_desc) { 158219820Sjeff free(p_node->print_desc); 159219820Sjeff } 160219820Sjeff} 161219820Sjeff 162219820Sjeff/********************************************************************** 163219820Sjeff **********************************************************************/ 164219820Sjeffvoid osm_node_delete(IN OUT osm_node_t ** const p_node) 165219820Sjeff{ 166219820Sjeff CL_ASSERT(p_node && *p_node); 167219820Sjeff osm_node_destroy(*p_node); 168219820Sjeff free(*p_node); 169219820Sjeff *p_node = NULL; 170219820Sjeff} 171219820Sjeff 172219820Sjeff/********************************************************************** 173219820Sjeff **********************************************************************/ 174219820Sjeffvoid 175219820Sjeffosm_node_link(IN osm_node_t * const p_node, 176219820Sjeff IN const uint8_t port_num, 177219820Sjeff IN osm_node_t * const p_remote_node, 178219820Sjeff IN const uint8_t remote_port_num) 179219820Sjeff{ 180219820Sjeff osm_physp_t *p_physp; 181219820Sjeff osm_physp_t *p_remote_physp; 182219820Sjeff 183219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 184219820Sjeff CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); 185219820Sjeff 186219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 187219820Sjeff p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); 188219820Sjeff 189219820Sjeff if (p_physp->p_remote_physp) 190219820Sjeff p_physp->p_remote_physp->p_remote_physp = NULL; 191219820Sjeff if (p_remote_physp->p_remote_physp) 192219820Sjeff p_remote_physp->p_remote_physp->p_remote_physp = NULL; 193219820Sjeff 194219820Sjeff osm_physp_link(p_physp, p_remote_physp); 195219820Sjeff} 196219820Sjeff 197219820Sjeff/********************************************************************** 198219820Sjeff **********************************************************************/ 199219820Sjeffvoid 200219820Sjeffosm_node_unlink(IN osm_node_t * const p_node, 201219820Sjeff IN const uint8_t port_num, 202219820Sjeff IN osm_node_t * const p_remote_node, 203219820Sjeff IN const uint8_t remote_port_num) 204219820Sjeff{ 205219820Sjeff osm_physp_t *p_physp; 206219820Sjeff osm_physp_t *p_remote_physp; 207219820Sjeff 208219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 209219820Sjeff CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); 210219820Sjeff 211219820Sjeff if (osm_node_link_exists(p_node, port_num, 212219820Sjeff p_remote_node, remote_port_num)) { 213219820Sjeff 214219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 215219820Sjeff p_remote_physp = 216219820Sjeff osm_node_get_physp_ptr(p_remote_node, remote_port_num); 217219820Sjeff 218219820Sjeff osm_physp_unlink(p_physp, p_remote_physp); 219219820Sjeff } 220219820Sjeff} 221219820Sjeff 222219820Sjeff/********************************************************************** 223219820Sjeff **********************************************************************/ 224219820Sjeffboolean_t 225219820Sjeffosm_node_link_exists(IN osm_node_t * const p_node, 226219820Sjeff IN const uint8_t port_num, 227219820Sjeff IN osm_node_t * const p_remote_node, 228219820Sjeff IN const uint8_t remote_port_num) 229219820Sjeff{ 230219820Sjeff osm_physp_t *p_physp; 231219820Sjeff osm_physp_t *p_remote_physp; 232219820Sjeff 233219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 234219820Sjeff CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); 235219820Sjeff 236219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 237219820Sjeff p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); 238219820Sjeff 239219820Sjeff return (osm_physp_link_exists(p_physp, p_remote_physp)); 240219820Sjeff} 241219820Sjeff 242219820Sjeff/********************************************************************** 243219820Sjeff **********************************************************************/ 244219820Sjeffboolean_t 245219820Sjeffosm_node_link_has_valid_ports(IN osm_node_t * const p_node, 246219820Sjeff IN const uint8_t port_num, 247219820Sjeff IN osm_node_t * const p_remote_node, 248219820Sjeff IN const uint8_t remote_port_num) 249219820Sjeff{ 250219820Sjeff osm_physp_t *p_physp; 251219820Sjeff osm_physp_t *p_remote_physp; 252219820Sjeff 253219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 254219820Sjeff CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size); 255219820Sjeff 256219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 257219820Sjeff p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num); 258219820Sjeff 259219820Sjeff return (p_physp && p_remote_physp); 260219820Sjeff} 261219820Sjeff 262219820Sjeff/********************************************************************** 263219820Sjeff **********************************************************************/ 264219820Sjeffboolean_t 265219820Sjeffosm_node_has_any_link(IN osm_node_t * const p_node, IN const uint8_t port_num) 266219820Sjeff{ 267219820Sjeff osm_physp_t *p_physp; 268219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 269219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 270219820Sjeff return (osm_physp_has_any_link(p_physp)); 271219820Sjeff} 272219820Sjeff 273219820Sjeff/********************************************************************** 274219820Sjeff **********************************************************************/ 275219820Sjeffosm_node_t *osm_node_get_remote_node(IN osm_node_t * const p_node, 276219820Sjeff IN const uint8_t port_num, 277219820Sjeff OUT uint8_t * p_remote_port_num) 278219820Sjeff{ 279219820Sjeff osm_physp_t *p_physp; 280219820Sjeff osm_physp_t *p_remote_physp; 281219820Sjeff 282219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 283219820Sjeff 284219820Sjeff if (!p_physp || !osm_physp_has_any_link(p_physp)) 285219820Sjeff return (NULL); 286219820Sjeff 287219820Sjeff p_remote_physp = osm_physp_get_remote(p_physp); 288219820Sjeff if (p_remote_port_num) 289219820Sjeff *p_remote_port_num = osm_physp_get_port_num(p_remote_physp); 290219820Sjeff 291219820Sjeff return (osm_physp_get_node_ptr(p_remote_physp)); 292219820Sjeff} 293219820Sjeff 294219820Sjeff/********************************************************************** 295219820Sjeff The lock must be held before calling this function. 296219820Sjeff**********************************************************************/ 297219820Sjeffib_net16_t 298219820Sjeffosm_node_get_remote_base_lid(IN osm_node_t * const p_node, 299219820Sjeff IN const uint32_t port_num) 300219820Sjeff{ 301219820Sjeff osm_physp_t *p_physp; 302219820Sjeff osm_physp_t *p_remote_physp; 303219820Sjeff CL_ASSERT(port_num < p_node->physp_tbl_size); 304219820Sjeff 305219820Sjeff p_physp = osm_node_get_physp_ptr(p_node, port_num); 306219820Sjeff if (p_physp) { 307219820Sjeff p_remote_physp = osm_physp_get_remote(p_physp); 308219820Sjeff return (osm_physp_get_base_lid(p_remote_physp)); 309219820Sjeff } 310219820Sjeff 311219820Sjeff return (0); 312219820Sjeff} 313