xref: /trueos/contrib/ofed/management/opensm/opensm/osm_node.c (revision 8fe640108653f13042f1b15213769e338aa524f6)
1 /*
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.
5  *
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:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
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.
24  *
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
32  * SOFTWARE.
33  *
34  */
35 
36 /*
37  * Abstract:
38  *    Implementation of osm_node_t.
39  * This object represents an Infiniband Node.
40  * This object is part of the opensm family of objects.
41  */
42 
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif				/* HAVE_CONFIG_H */
46 
47 #include <stdlib.h>
48 #include <iba/ib_types.h>
49 #include <opensm/osm_node.h>
50 #include <opensm/osm_madw.h>
51 
52 /**********************************************************************
53  **********************************************************************/
54 void
osm_node_init_physp(IN osm_node_t * const p_node,IN const osm_madw_t * const p_madw)55 osm_node_init_physp(IN osm_node_t * const p_node,
56 		    IN const osm_madw_t * const p_madw)
57 {
58 	ib_net64_t port_guid;
59 	ib_smp_t *p_smp;
60 	ib_node_info_t *p_ni;
61 	uint8_t port_num;
62 
63 	p_smp = osm_madw_get_smp_ptr(p_madw);
64 
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);
68 
69 	CL_ASSERT(port_num < p_node->physp_tbl_size);
70 
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);
75 }
76 
77 /**********************************************************************
78  **********************************************************************/
node_init_physp0(IN osm_node_t * const p_node,IN const osm_madw_t * const p_madw)79 static void node_init_physp0(IN osm_node_t * const p_node,
80 			     IN const osm_madw_t * const p_madw)
81 {
82 	ib_smp_t *p_smp;
83 	ib_node_info_t *p_ni;
84 
85 	p_smp = osm_madw_get_smp_ptr(p_madw);
86 	p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
87 
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);
92 }
93 
94 /**********************************************************************
95  **********************************************************************/
osm_node_new(IN const osm_madw_t * const p_madw)96 osm_node_t *osm_node_new(IN const osm_madw_t * const p_madw)
97 {
98 	osm_node_t *p_node;
99 	ib_smp_t *p_smp;
100 	ib_node_info_t *p_ni;
101 	uint8_t i;
102 	uint32_t size;
103 
104 	p_smp = osm_madw_get_smp_ptr(p_madw);
105 	p_ni = (ib_node_info_t *) ib_smp_get_payload_ptr(p_smp);
106 
107 	/*
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".
113 	 */
114 	size = p_ni->num_ports;
115 
116 	p_node = malloc(sizeof(*p_node) + sizeof(osm_physp_t) * size);
117 	if (!p_node)
118 		return NULL;
119 
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;
123 
124 	/*
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
131 	   Get(NodeInfo).
132 	 */
133 	for (i = 0; i < p_node->physp_tbl_size; i++)
134 		osm_physp_construct(&p_node->physp_table[i]);
135 
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);
140 
141 	return (p_node);
142 }
143 
144 /**********************************************************************
145  **********************************************************************/
osm_node_destroy(IN osm_node_t * p_node)146 static void osm_node_destroy(IN osm_node_t * p_node)
147 {
148 	uint16_t i;
149 
150 	/*
151 	   Cleanup all physports
152 	 */
153 	for (i = 0; i < p_node->physp_tbl_size; i++)
154 		osm_physp_destroy(&p_node->physp_table[i]);
155 
156 	/* cleanup printable node_desc field */
157 	if (p_node->print_desc) {
158 		free(p_node->print_desc);
159 	}
160 }
161 
162 /**********************************************************************
163  **********************************************************************/
osm_node_delete(IN OUT osm_node_t ** const p_node)164 void osm_node_delete(IN OUT osm_node_t ** const p_node)
165 {
166 	CL_ASSERT(p_node && *p_node);
167 	osm_node_destroy(*p_node);
168 	free(*p_node);
169 	*p_node = NULL;
170 }
171 
172 /**********************************************************************
173  **********************************************************************/
174 void
osm_node_link(IN osm_node_t * const p_node,IN const uint8_t port_num,IN osm_node_t * const p_remote_node,IN const uint8_t remote_port_num)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)
179 {
180 	osm_physp_t *p_physp;
181 	osm_physp_t *p_remote_physp;
182 
183 	CL_ASSERT(port_num < p_node->physp_tbl_size);
184 	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
185 
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);
188 
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;
193 
194 	osm_physp_link(p_physp, p_remote_physp);
195 }
196 
197 /**********************************************************************
198  **********************************************************************/
199 void
osm_node_unlink(IN osm_node_t * const p_node,IN const uint8_t port_num,IN osm_node_t * const p_remote_node,IN const uint8_t remote_port_num)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)
204 {
205 	osm_physp_t *p_physp;
206 	osm_physp_t *p_remote_physp;
207 
208 	CL_ASSERT(port_num < p_node->physp_tbl_size);
209 	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
210 
211 	if (osm_node_link_exists(p_node, port_num,
212 				 p_remote_node, remote_port_num)) {
213 
214 		p_physp = osm_node_get_physp_ptr(p_node, port_num);
215 		p_remote_physp =
216 		    osm_node_get_physp_ptr(p_remote_node, remote_port_num);
217 
218 		osm_physp_unlink(p_physp, p_remote_physp);
219 	}
220 }
221 
222 /**********************************************************************
223  **********************************************************************/
224 boolean_t
osm_node_link_exists(IN osm_node_t * const p_node,IN const uint8_t port_num,IN osm_node_t * const p_remote_node,IN const uint8_t remote_port_num)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)
229 {
230 	osm_physp_t *p_physp;
231 	osm_physp_t *p_remote_physp;
232 
233 	CL_ASSERT(port_num < p_node->physp_tbl_size);
234 	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
235 
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);
238 
239 	return (osm_physp_link_exists(p_physp, p_remote_physp));
240 }
241 
242 /**********************************************************************
243  **********************************************************************/
244 boolean_t
osm_node_link_has_valid_ports(IN osm_node_t * const p_node,IN const uint8_t port_num,IN osm_node_t * const p_remote_node,IN const uint8_t remote_port_num)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)
249 {
250 	osm_physp_t *p_physp;
251 	osm_physp_t *p_remote_physp;
252 
253 	CL_ASSERT(port_num < p_node->physp_tbl_size);
254 	CL_ASSERT(remote_port_num < p_remote_node->physp_tbl_size);
255 
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);
258 
259 	return (p_physp && p_remote_physp);
260 }
261 
262 /**********************************************************************
263  **********************************************************************/
264 boolean_t
osm_node_has_any_link(IN osm_node_t * const p_node,IN const uint8_t port_num)265 osm_node_has_any_link(IN osm_node_t * const p_node, IN const uint8_t port_num)
266 {
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));
271 }
272 
273 /**********************************************************************
274  **********************************************************************/
osm_node_get_remote_node(IN osm_node_t * const p_node,IN const uint8_t port_num,OUT uint8_t * p_remote_port_num)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)
278 {
279 	osm_physp_t *p_physp;
280 	osm_physp_t *p_remote_physp;
281 
282 	p_physp = osm_node_get_physp_ptr(p_node, port_num);
283 
284 	if (!p_physp || !osm_physp_has_any_link(p_physp))
285 		return (NULL);
286 
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);
290 
291 	return (osm_physp_get_node_ptr(p_remote_physp));
292 }
293 
294 /**********************************************************************
295  The lock must be held before calling this function.
296 **********************************************************************/
297 ib_net16_t
osm_node_get_remote_base_lid(IN osm_node_t * const p_node,IN const uint32_t port_num)298 osm_node_get_remote_base_lid(IN osm_node_t * const p_node,
299 			     IN const uint32_t port_num)
300 {
301 	osm_physp_t *p_physp;
302 	osm_physp_t *p_remote_physp;
303 	CL_ASSERT(port_num < p_node->physp_tbl_size);
304 
305 	p_physp = osm_node_get_physp_ptr(p_node, port_num);
306 	if (p_physp) {
307 		p_remote_physp = osm_physp_get_remote(p_physp);
308 		return (osm_physp_get_base_lid(p_remote_physp));
309 	}
310 
311 	return (0);
312 }
313