2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Implementation of osm_node_t.
39 * This object represents an Infiniband Node.
40 * This object is part of the opensm family of objects.
45 #endif /* HAVE_CONFIG_H */
48 #include <iba/ib_types.h>
49 #include <opensm/osm_file_ids.h>
50 #define FILE_ID OSM_FILE_NODE_C
51 #include <opensm/osm_node.h>
52 #include <opensm/osm_madw.h>
54 void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num,
55 IN const osm_madw_t * p_madw)
61 p_smp = osm_madw_get_smp_ptr(p_madw);
63 p_ni = ib_smp_get_payload_ptr(p_smp);
64 port_guid = p_ni->port_guid;
66 CL_ASSERT(port_num < p_node->physp_tbl_size);
68 osm_physp_init(&p_node->physp_table[port_num],
69 port_guid, port_num, p_node,
70 osm_madw_get_bind_handle(p_madw),
71 p_smp->hop_count, p_smp->initial_path);
74 osm_node_t *osm_node_new(IN const osm_madw_t * p_madw)
82 p_smp = osm_madw_get_smp_ptr(p_madw);
83 p_ni = ib_smp_get_payload_ptr(p_smp);
86 The node object already contains one physical port object.
87 Therefore, subtract 1 from the number of physical ports
88 used by the switch. This is not done for CA's since they
89 need to occupy 1 more physp than they physically have since
90 we still reserve room for a "port 0".
92 size = p_ni->num_ports;
94 p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
98 memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
99 p_node->node_info = *p_ni;
100 p_node->physp_tbl_size = size + 1;
102 p_node->physp_discovered = malloc(sizeof(uint8_t) * p_node->physp_tbl_size);
103 if (!p_node->physp_discovered) {
107 memset(p_node->physp_discovered, 0, sizeof(uint8_t) * p_node->physp_tbl_size);
109 Construct Physical Port objects owned by this Node.
110 Then, initialize the Physical Port through with we
111 discovered this port.
112 For switches, all ports have the same GUID.
113 For CAs and routers, each port has a different GUID, so we only
114 know the GUID for the port that responded to our
117 for (i = 0; i < p_node->physp_tbl_size; i++)
118 osm_physp_construct(&p_node->physp_table[i]);
120 if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
121 for (i = 0; i <= p_ni->num_ports; i++)
122 osm_node_init_physp(p_node, i, p_madw);
124 osm_node_init_physp(p_node,
125 ib_node_info_get_local_port_num(p_ni),
127 p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
132 static void node_destroy(IN osm_node_t * p_node)
137 Cleanup all physports
139 for (i = 0; i < p_node->physp_tbl_size; i++)
140 osm_physp_destroy(&p_node->physp_table[i]);
142 /* cleanup printable node_desc field */
143 if (p_node->print_desc)
144 free(p_node->print_desc);
146 /* cleanup physp_discovered array */
147 free(p_node->physp_discovered);
150 void osm_node_delete(IN OUT osm_node_t ** p_node)
152 CL_ASSERT(p_node && *p_node);
153 node_destroy(*p_node);
158 void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num,
159 IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
161 osm_physp_t *p_physp;
162 osm_physp_t *p_remote_physp;
164 p_physp = osm_node_get_physp_ptr(p_node, port_num);
165 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
167 if (p_physp->p_remote_physp)
168 p_physp->p_remote_physp->p_remote_physp = NULL;
169 if (p_remote_physp->p_remote_physp)
170 p_remote_physp->p_remote_physp->p_remote_physp = NULL;
172 osm_physp_link(p_physp, p_remote_physp);
175 void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num,
176 IN osm_node_t * p_remote_node, IN uint8_t remote_port_num)
178 osm_physp_t *p_physp;
179 osm_physp_t *p_remote_physp;
181 CL_ASSERT(port_num < p_node->physp_tbl_size);
182 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
184 if (osm_node_link_exists(p_node, port_num,
185 p_remote_node, remote_port_num)) {
187 p_physp = osm_node_get_physp_ptr(p_node, port_num);
189 osm_node_get_physp_ptr(p_remote_node, remote_port_num);
191 osm_physp_unlink(p_physp, p_remote_physp);
195 boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num,
196 IN osm_node_t * p_remote_node,
197 IN uint8_t remote_port_num)
199 osm_physp_t *p_physp;
200 osm_physp_t *p_remote_physp;
202 CL_ASSERT(port_num < p_node->physp_tbl_size);
203 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
205 p_physp = osm_node_get_physp_ptr(p_node, port_num);
206 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
208 return osm_physp_link_exists(p_physp, p_remote_physp);
211 boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node,
213 IN osm_node_t * p_remote_node,
214 IN uint8_t remote_port_num)
216 osm_physp_t *p_physp;
217 osm_physp_t *p_remote_physp;
219 CL_ASSERT(port_num < p_node->physp_tbl_size);
220 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
222 p_physp = osm_node_get_physp_ptr(p_node, port_num);
223 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
225 return (p_physp && p_remote_physp);
228 boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num)
230 osm_physp_t *p_physp;
231 CL_ASSERT(port_num < p_node->physp_tbl_size);
232 p_physp = osm_node_get_physp_ptr(p_node, port_num);
233 return osm_physp_has_any_link(p_physp);
236 osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node,
238 OUT uint8_t * p_remote_port_num)
240 osm_physp_t *p_physp;
241 osm_physp_t *p_remote_physp;
243 p_physp = osm_node_get_physp_ptr(p_node, port_num);
245 if (!p_physp || !osm_physp_has_any_link(p_physp))
248 p_remote_physp = osm_physp_get_remote(p_physp);
249 if (p_remote_port_num)
250 *p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
252 return osm_physp_get_node_ptr(p_remote_physp);
255 /**********************************************************************
256 The lock must be held before calling this function.
257 **********************************************************************/
258 ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node,
259 IN uint32_t port_num)
261 osm_physp_t *p_physp;
262 osm_physp_t *p_remote_physp;
263 CL_ASSERT(port_num < p_node->physp_tbl_size);
265 p_physp = osm_node_get_physp_ptr(p_node, port_num);
267 p_remote_physp = osm_physp_get_remote(p_physp);
268 return osm_physp_get_base_lid(p_remote_physp);