2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2005 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_node.h>
50 #include <opensm/osm_madw.h>
52 /**********************************************************************
53 **********************************************************************/
55 osm_node_init_physp(IN osm_node_t * const p_node,
56 IN const osm_madw_t * const p_madw)
63 p_smp = osm_madw_get_smp_ptr(p_madw);
65 p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
66 port_guid = p_ni->port_guid;
67 port_num = ib_node_info_get_local_port_num(p_ni);
69 CL_ASSERT(port_num < p_node->physp_tbl_size);
71 osm_physp_init(&p_node->physp_table[port_num],
72 port_guid, port_num, p_node,
73 osm_madw_get_bind_handle(p_madw),
74 p_smp->hop_count, p_smp->initial_path);
77 /**********************************************************************
78 **********************************************************************/
79 static void node_init_physp0(IN osm_node_t * const p_node,
80 IN const osm_madw_t * const p_madw)
85 p_smp = osm_madw_get_smp_ptr(p_madw);
86 p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
88 osm_physp_init(&p_node->physp_table[0],
89 p_ni->port_guid, 0, p_node,
90 osm_madw_get_bind_handle(p_madw),
91 p_smp->hop_count, p_smp->initial_path);
94 /**********************************************************************
95 **********************************************************************/
96 osm_node_t *osm_node_new(IN const osm_madw_t * const p_madw)
100 ib_node_info_t *p_ni;
104 p_smp = osm_madw_get_smp_ptr(p_madw);
105 p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
108 The node object already contains one physical port object.
109 Therefore, subtract 1 from the number of physical ports
110 used by the switch. This is not done for CA's since they
111 need to occupy 1 more physp than they physically have since
112 we still reserve room for a "port 0".
114 size = p_ni->num_ports;
116 p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
120 memset(p_node, 0, sizeof(*p_node) + sizeof(osm_physp_t) * size);
121 p_node->node_info = *p_ni;
122 p_node->physp_tbl_size = size + 1;
125 Construct Physical Port objects owned by this Node.
126 Then, initialize the Physical Port through with we
127 discovered this port.
128 For switches, all ports have the same GUID.
129 For CAs and routers, each port has a different GUID, so we only
130 know the GUID for the port that responded to our
133 for (i = 0; i < p_node->physp_tbl_size; i++)
134 osm_physp_construct(&p_node->physp_table[i]);
136 osm_node_init_physp(p_node, p_madw);
137 if (p_ni->node_type == IB_NODE_TYPE_SWITCH)
138 node_init_physp0(p_node, p_madw);
139 p_node->print_desc = strdup(OSM_NODE_DESC_UNKNOWN);
144 /**********************************************************************
145 **********************************************************************/
146 static void osm_node_destroy(IN osm_node_t * p_node)
151 Cleanup all physports
153 for (i = 0; i < p_node->physp_tbl_size; i++)
154 osm_physp_destroy(&p_node->physp_table[i]);
156 /* cleanup printable node_desc field */
157 if (p_node->print_desc) {
158 free(p_node->print_desc);
162 /**********************************************************************
163 **********************************************************************/
164 void osm_node_delete(IN OUT osm_node_t ** const p_node)
166 CL_ASSERT(p_node && *p_node);
167 osm_node_destroy(*p_node);
172 /**********************************************************************
173 **********************************************************************/
175 osm_node_link(IN osm_node_t * const p_node,
176 IN const uint8_t port_num,
177 IN osm_node_t * const p_remote_node,
178 IN const uint8_t remote_port_num)
180 osm_physp_t *p_physp;
181 osm_physp_t *p_remote_physp;
183 CL_ASSERT(port_num < p_node->physp_tbl_size);
184 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
186 p_physp = osm_node_get_physp_ptr(p_node, port_num);
187 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
189 if (p_physp->p_remote_physp)
190 p_physp->p_remote_physp->p_remote_physp = NULL;
191 if (p_remote_physp->p_remote_physp)
192 p_remote_physp->p_remote_physp->p_remote_physp = NULL;
194 osm_physp_link(p_physp, p_remote_physp);
197 /**********************************************************************
198 **********************************************************************/
200 osm_node_unlink(IN osm_node_t * const p_node,
201 IN const uint8_t port_num,
202 IN osm_node_t * const p_remote_node,
203 IN const uint8_t remote_port_num)
205 osm_physp_t *p_physp;
206 osm_physp_t *p_remote_physp;
208 CL_ASSERT(port_num < p_node->physp_tbl_size);
209 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
211 if (osm_node_link_exists(p_node, port_num,
212 p_remote_node, remote_port_num)) {
214 p_physp = osm_node_get_physp_ptr(p_node, port_num);
216 osm_node_get_physp_ptr(p_remote_node, remote_port_num);
218 osm_physp_unlink(p_physp, p_remote_physp);
222 /**********************************************************************
223 **********************************************************************/
225 osm_node_link_exists(IN osm_node_t * const p_node,
226 IN const uint8_t port_num,
227 IN osm_node_t * const p_remote_node,
228 IN const uint8_t remote_port_num)
230 osm_physp_t *p_physp;
231 osm_physp_t *p_remote_physp;
233 CL_ASSERT(port_num < p_node->physp_tbl_size);
234 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
236 p_physp = osm_node_get_physp_ptr(p_node, port_num);
237 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
239 return (osm_physp_link_exists(p_physp, p_remote_physp));
242 /**********************************************************************
243 **********************************************************************/
245 osm_node_link_has_valid_ports(IN osm_node_t * const p_node,
246 IN const uint8_t port_num,
247 IN osm_node_t * const p_remote_node,
248 IN const uint8_t remote_port_num)
250 osm_physp_t *p_physp;
251 osm_physp_t *p_remote_physp;
253 CL_ASSERT(port_num < p_node->physp_tbl_size);
254 CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
256 p_physp = osm_node_get_physp_ptr(p_node, port_num);
257 p_remote_physp = osm_node_get_physp_ptr(p_remote_node, remote_port_num);
259 return (p_physp && p_remote_physp);
262 /**********************************************************************
263 **********************************************************************/
265 osm_node_has_any_link(IN osm_node_t * const p_node, IN const uint8_t port_num)
267 osm_physp_t *p_physp;
268 CL_ASSERT(port_num < p_node->physp_tbl_size);
269 p_physp = osm_node_get_physp_ptr(p_node, port_num);
270 return (osm_physp_has_any_link(p_physp));
273 /**********************************************************************
274 **********************************************************************/
275 osm_node_t *osm_node_get_remote_node(IN osm_node_t * const p_node,
276 IN const uint8_t port_num,
277 OUT uint8_t * p_remote_port_num)
279 osm_physp_t *p_physp;
280 osm_physp_t *p_remote_physp;
282 p_physp = osm_node_get_physp_ptr(p_node, port_num);
284 if (!p_physp || !osm_physp_has_any_link(p_physp))
287 p_remote_physp = osm_physp_get_remote(p_physp);
288 if (p_remote_port_num)
289 *p_remote_port_num = osm_physp_get_port_num(p_remote_physp);
291 return (osm_physp_get_node_ptr(p_remote_physp));
294 /**********************************************************************
295 The lock must be held before calling this function.
296 **********************************************************************/
298 osm_node_get_remote_base_lid(IN osm_node_t * const p_node,
299 IN const uint32_t port_num)
301 osm_physp_t *p_physp;
302 osm_physp_t *p_remote_physp;
303 CL_ASSERT(port_num < p_node->physp_tbl_size);
305 p_physp = osm_node_get_physp_ptr(p_node, port_num);
307 p_remote_physp = osm_physp_get_remote(p_physp);
308 return (osm_physp_get_base_lid(p_remote_physp));