1 /*
2  * Copyright (c) 2004-2009 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  * 	Declaration of osm_node_t.
39  *	This object represents an IBA node.
40  *	This object is part of the OpenSM family of objects.
41  */
42 
43 #ifndef _OSM_NODE_H_
44 #define _OSM_NODE_H_
45 
46 #include <complib/cl_qmap.h>
47 #include <iba/ib_types.h>
48 #include <opensm/osm_base.h>
49 #include <opensm/osm_port.h>
50 #include <opensm/osm_path.h>
51 #include <opensm/osm_madw.h>
52 
53 #ifdef __cplusplus
54 #  define BEGIN_C_DECLS extern "C" {
55 #  define END_C_DECLS   }
56 #else				/* !__cplusplus */
57 #  define BEGIN_C_DECLS
58 #  define END_C_DECLS
59 #endif				/* __cplusplus */
60 
61 BEGIN_C_DECLS
62 
63 struct osm_switch;
64 
65 /****h* OpenSM/Node
66 * NAME
67 *	Node
68 *
69 * DESCRIPTION
70 *	The Node object encapsulates the information needed by the
71 *	OpenSM to manage nodes.  The OpenSM allocates one Node object
72 *	per node in the IBA subnet.
73 *
74 *	The Node object is not thread safe, thus callers must provide
75 *	serialization.
76 *
77 *	This object should be treated as opaque and should be
78 *	manipulated only through the provided functions.
79 *
80 * AUTHOR
81 *	Steve King, Intel
82 *
83 *********/
84 
85 /****s* OpenSM: Node/osm_node_t
86 * NAME
87 *	osm_node_t
88 *
89 * DESCRIPTION
90 *	Node structure.
91 *
92 *	This object should be treated as opaque and should
93 *	be manipulated only through the provided functions.
94 *
95 * SYNOPSIS
96 */
97 typedef struct osm_node {
98 	cl_map_item_t map_item;
99 	struct osm_switch *sw;
100 	ib_node_info_t node_info;
101 	ib_node_desc_t node_desc;
102 	uint32_t discovery_count;
103 	uint32_t physp_tbl_size;
104 	char *print_desc;
105 	uint8_t *physp_discovered;
106 	osm_physp_t physp_table[1];
107 } osm_node_t;
108 /*
109 * FIELDS
110 *	map_item
111 *		Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
112 *
113 *	sw
114 *		For switch node contains pointer to appropriate osm_switch
115 *		structure. NULL for non-switch nodes. Can be used for fast
116 *		access to switch object and for simple node type detection
117 *
118 *	node_info
119 *		The IBA defined NodeInfo data for this node.
120 *
121 *	node_desc
122 *		The IBA defined NodeDescription data for this node.
123 *
124 *	discovery_count
125 *		The number of times this node has been discovered
126 *		during the current fabric sweep.  This number is reset
127 *		to zero at the start of a sweep.
128 *
129 *	physp_tbl_size
130 *		The size of the physp_table array.  This value is one greater
131 *		than the number of ports in the node, since port numbers
132 *		start with 1 for some bizarre reason.
133 *
134 *	print_desc
135 *		A printable version of the node description.
136 *
137 *	physp_discovered
138 *		Array of physp_discovered objects for all ports of this node.
139 *		Each object indiactes whether the port has been discovered
140 *		during the sweep or not. 1 means that the port had been discovered.
141 *
142 *	physp_table
143 *		Array of physical port objects belonging to this node.
144 *		Index is contiguous by local port number.
145 *		For switches, port 0 is the always the management port (14.2.5.6).
146 *		MUST BE LAST MEMBER! - Since it grows !!!!
147 *
148 * SEE ALSO
149 *	Node object
150 *********/
151 
152 /****f* OpenSM: Node/osm_node_delete
153 * NAME
154 *	osm_node_delete
155 *
156 * DESCRIPTION
157 *	The osm_node_delete function destroys a node, releasing
158 *	all resources.
159 *
160 * SYNOPSIS
161 */
162 void osm_node_delete(IN OUT osm_node_t ** p_node);
163 /*
164 * PARAMETERS
165 *	p_node
166 *		[in][out] Pointer to a Pointer a Node object to destroy.
167 *		On return, the pointer to set to NULL.
168 *
169 * RETURN VALUE
170 *	This function does not return a value.
171 *
172 * NOTES
173 *	Performs any necessary cleanup of the specified Node object.
174 *	This function should only be called after a call to osm_node_new.
175 *
176 * SEE ALSO
177 *	Node object, osm_node_new
178 *********/
179 
180 /****f* OpenSM: Node/osm_node_new
181 * NAME
182 *	osm_node_new
183 *
184 * DESCRIPTION
185 *	The osm_node_new function initializes a Node object for use.
186 *
187 * SYNOPSIS
188 */
189 osm_node_t *osm_node_new(IN const osm_madw_t * p_madw);
190 /*
191 * PARAMETERS
192 *	p_madw
193 *		[in] Pointer to a osm_madw_t object containing a mad with
194 *		the node's NodeInfo attribute.  The caller may discard the
195 *		osm_madw_t structure after calling osm_node_new.
196 *
197 * RETURN VALUES
198 *	On success, a pointer to the new initialized osm_node_t structure.
199 *	NULL otherwise.
200 *
201 * NOTES
202 *
203 * SEE ALSO
204 *	Node object
205 *********/
206 
207 /****f* OpenSM: Node/osm_node_get_physp_ptr
208 * NAME
209 *	osm_node_get_physp_ptr
210 *
211 * DESCRIPTION
212 *	Returns a pointer to the physical port object at the
213 *	specified local port number.
214 *
215 * SYNOPSIS
216 */
217 static inline osm_physp_t *osm_node_get_physp_ptr(IN osm_node_t * p_node,
218 						  IN uint32_t port_num)
219 {
220 
221 	CL_ASSERT(port_num < p_node->physp_tbl_size);
222 	return osm_physp_is_valid(&p_node->physp_table[port_num]) ?
223 		&p_node->physp_table[port_num] : NULL;
224 }
225 
226 /*
227 * PARAMETERS
228 *	p_node
229 *		[in] Pointer to an osm_node_t object.
230 *
231 *	port_num
232 *		[in] Local port number.
233 *
234 * RETURN VALUES
235 *	Returns a pointer to the physical port object at the
236 *	specified local port number.
237 *	A return value of zero means the port number was out of range.
238 *
239 * NOTES
240 *
241 * SEE ALSO
242 *	Node object
243 *********/
244 
245 /****f* OpenSM: Node/osm_node_get_type
246 * NAME
247 *	osm_node_get_type
248 *
249 * DESCRIPTION
250 *	Returns the type of this node.
251 *
252 * SYNOPSIS
253 */
254 static inline uint8_t osm_node_get_type(IN const osm_node_t * p_node)
255 {
256 	return p_node->node_info.node_type;
257 }
258 
259 /*
260 * PARAMETERS
261 *	p_node
262 *		[in] Pointer to an osm_node_t object.
263 *
264 * RETURN VALUES
265 *	Returns the IBA defined type of this node.
266 *
267 * NOTES
268 *
269 * SEE ALSO
270 *	Node object
271 *********/
272 
273 /****f* OpenSM: Node/osm_node_get_num_physp
274 * NAME
275 *	osm_node_get_num_physp
276 *
277 * DESCRIPTION
278 *	Returns the number of osm_physp ports allocated for this node.
279 *	For switches, it is the number of external physical ports plus
280 *	port 0. For CAs and routers, it is the number of external physical
281 *	ports plus 1.
282 *
283 * SYNOPSIS
284 */
285 static inline uint8_t osm_node_get_num_physp(IN const osm_node_t * p_node)
286 {
287 	return (uint8_t) p_node->physp_tbl_size;
288 }
289 
290 /*
291 * PARAMETERS
292 *	p_node
293 *		[in] Pointer to an osm_node_t object.
294 *
295 * RETURN VALUES
296 *	Returns the IBA defined type of this node.
297 *
298 * NOTES
299 *
300 * SEE ALSO
301 *	Node object
302 *********/
303 
304 /****f* OpenSM: Node/osm_node_get_remote_node
305 * NAME
306 *	osm_node_get_remote_node
307 *
308 * DESCRIPTION
309 *	Returns a pointer to the node on the other end of the
310 *	specified port.
311 *	Returns NULL if no remote node exists.
312 *
313 * SYNOPSIS
314 */
315 osm_node_t *osm_node_get_remote_node(IN osm_node_t * p_node,
316 				     IN uint8_t port_num,
317 				     OUT uint8_t * p_remote_port_num);
318 /*
319 * PARAMETERS
320 *	p_node
321 *		[in] Pointer to an osm_node_t object.
322 *
323 *	port_num
324 *		[in] Port number in p_node through which to get the remote node.
325 *
326 *	p_remote_port_num
327 *		[out] Port number in the remote's node through which this
328 *		link exists.  The caller may specify NULL for this pointer
329 *		if the port number isn't needed.
330 *
331 * RETURN VALUES
332 *	Returns a pointer to the node on the other end of the
333 *	specified port.
334 *	Returns NULL if no remote node exists.
335 *
336 * NOTES
337 *
338 * SEE ALSO
339 *	Node object
340 *********/
341 
342 /****f* OpenSM: Node/osm_node_get_base_lid
343 * NAME
344 *	osm_node_get_base_lid
345 *
346 * DESCRIPTION
347 *	Returns the LID value of the specified port on this node.
348 *
349 * SYNOPSIS
350 */
351 static inline ib_net16_t osm_node_get_base_lid(IN const osm_node_t * p_node,
352 					       IN uint32_t port_num)
353 {
354 	CL_ASSERT(port_num < p_node->physp_tbl_size);
355 	return osm_physp_get_base_lid(&p_node->physp_table[port_num]);
356 }
357 
358 /*
359 * PARAMETERS
360 *	p_node
361 *		[in] Pointer to an osm_node_t object.
362 *
363 *	port_num
364 *		[in] Local port number.
365 *
366 * RETURN VALUES
367 *	Returns a pointer to the physical port object at the
368 *	specified local port number.
369 *	A return value of zero means the port number was out of range.
370 *
371 * NOTES
372 *
373 * SEE ALSO
374 *	Node object
375 *********/
376 
377 /****f* OpenSM: Node/osm_node_get_remote_base_lid
378 * NAME
379 *	osm_node_get_remote_base_lid
380 *
381 * DESCRIPTION
382 *	Returns the base LID value of the port on the other side
383 *	of the wire from the specified port on this node.
384 *
385 * SYNOPSIS
386 */
387 ib_net16_t osm_node_get_remote_base_lid(IN osm_node_t * p_node,
388 					IN uint32_t port_num);
389 /*
390 * PARAMETERS
391 *	p_node
392 *		[in] Pointer to an osm_node_t object.
393 *
394 *	port_num
395 *		[in] Local port number.
396 *
397 * RETURN VALUES
398 *	Returns a pointer to the physical port object at the
399 *	specified local port number.
400 *	A return value of zero means the port number was out of range.
401 *
402 * NOTES
403 *
404 * SEE ALSO
405 *	Node object
406 *********/
407 
408 /****f* OpenSM: Node/osm_node_get_lmc
409 * NAME
410 *	osm_node_get_lmc
411 *
412 * DESCRIPTION
413 *	Returns the LMC value of the specified port on this node.
414 *
415 * SYNOPSIS
416 */
417 static inline uint8_t osm_node_get_lmc(IN const osm_node_t * p_node,
418 				       IN uint32_t port_num)
419 {
420 	CL_ASSERT(port_num < p_node->physp_tbl_size);
421 	return osm_physp_get_lmc(&p_node->physp_table[port_num]);
422 }
423 
424 /*
425 * PARAMETERS
426 *	p_node
427 *		[in] Pointer to an osm_node_t object.
428 *
429 *	port_num
430 *		[in] Local port number.
431 *
432 * RETURN VALUES
433 *	Returns the LMC value of the specified port on this node.
434 *
435 * NOTES
436 *
437 * SEE ALSO
438 *	Node object
439 *********/
440 
441 /****f* OpenSM: Node/osm_node_init_physp
442 * NAME
443 *	osm_node_init_physp
444 *
445 * DESCRIPTION
446 *	Initializes a physical port for the given node.
447 *
448 * SYNOPSIS
449 */
450 void osm_node_init_physp(IN osm_node_t * p_node, uint8_t port_num,
451 			 IN const osm_madw_t * p_madw);
452 /*
453 * PARAMETERS
454 *	p_node
455 *		[in] Pointer to an osm_node_t object.
456 *
457 *	p_madw
458 *		[in] Pointer to a osm_madw_t object containing a mad with
459 *		the node's NodeInfo attribute as discovered through the
460 *		Physical Port to add to the node.  The caller may discard the
461 *		osm_madw_t structure after calling osm_node_new.
462 *
463 * RETURN VALUES
464 *	None.
465 *
466 * NOTES
467 *
468 * SEE ALSO
469 *	Node object, Physical Port object.
470 *********/
471 
472 /****f* OpenSM: Node/osm_node_get_node_guid
473 * NAME
474 *	osm_node_get_node_guid
475 *
476 * DESCRIPTION
477 *	Returns the node GUID of this node.
478 *
479 * SYNOPSIS
480 */
481 static inline ib_net64_t osm_node_get_node_guid(IN const osm_node_t * p_node)
482 {
483 	return p_node->node_info.node_guid;
484 }
485 
486 /*
487 * PARAMETERS
488 *	p_node
489 *		[in] Pointer to an osm_node_t object.
490 *
491 * RETURN VALUES
492 *	Returns the node GUID of this node.
493 *
494 * NOTES
495 *
496 * SEE ALSO
497 *	Node object
498 *********/
499 
500 /****f* OpenSM: Node/osm_node_link
501 * NAME
502 *	osm_node_link
503 *
504 * DESCRIPTION
505 *	Logically connects a node to another node through the specified port.
506 *
507 * SYNOPSIS
508 */
509 void osm_node_link(IN osm_node_t * p_node, IN uint8_t port_num,
510 		   IN osm_node_t * p_remote_node, IN uint8_t remote_port_num);
511 /*
512 * PARAMETERS
513 *	p_node
514 *		[in] Pointer to an osm_node_t object.
515 *
516 *	port_num
517 *		[in] Port number in p_node through which to create the link.
518 *
519 *	p_remote_node
520 *		[in] Pointer to the remote port object.
521 *
522 *	remote_port_num
523 *		[in] Port number in the remote's node through which to
524 *		create this link.
525 *
526 * RETURN VALUES
527 *	None.
528 *
529 * NOTES
530 *
531 * SEE ALSO
532 *	Node object
533 *********/
534 
535 /****f* OpenSM: Node/osm_node_unlink
536 * NAME
537 *	osm_node_unlink
538 *
539 * DESCRIPTION
540 *	Logically disconnects a node from another node through
541 *	the specified port.
542 *
543 * SYNOPSIS
544 */
545 void osm_node_unlink(IN osm_node_t * p_node, IN uint8_t port_num,
546 		     IN osm_node_t * p_remote_node, IN uint8_t remote_port_num);
547 /*
548 * PARAMETERS
549 *	p_node
550 *		[in] Pointer to an osm_node_t object.
551 *
552 *	port_num
553 *		[in] Port number in p_node through which to unlink.
554 *
555 *	p_remote_node
556 *		[in] Pointer to the remote port object.
557 *
558 *	remote_port_num
559 *		[in] Port number in the remote's node through which to unlink.
560 *
561 * RETURN VALUES
562 *	None.
563 *
564 * NOTES
565 *
566 * SEE ALSO
567 *	Node object
568 *********/
569 
570 /****f* OpenSM: Node/osm_node_link_exists
571 * NAME
572 *	osm_node_link_exists
573 *
574 * DESCRIPTION
575 *	Return TRUE if a link exists between the specified nodes on
576 *	the specified ports.
577 *	Returns FALSE otherwise.
578 *
579 * SYNOPSIS
580 */
581 boolean_t osm_node_link_exists(IN osm_node_t * p_node, IN uint8_t port_num,
582 			       IN osm_node_t * p_remote_node,
583 			       IN uint8_t remote_port_num);
584 /*
585 * PARAMETERS
586 *	p_node
587 *		[in] Pointer to an osm_node_t object.
588 *
589 *	port_num
590 *		[in] Port number in p_node through which to check the link.
591 *
592 *	p_remote_node
593 *		[in] Pointer to the remote port object.
594 *
595 *	remote_port_num
596 *		[in] Port number in the remote's node through which to
597 *		check this link.
598 *
599 * RETURN VALUES
600 *	Return TRUE if a link exists between the specified nodes on
601 *	the specified ports.
602 *	Returns FALSE otherwise.
603 *
604 * NOTES
605 *
606 * SEE ALSO
607 *	Node object
608 *********/
609 
610 /****f* OpenSM: Node/osm_node_has_any_link
611 * NAME
612 *	osm_node_has_any_link
613 *
614 * DESCRIPTION
615 *	Return TRUE if a any link exists from the specified nodes on
616 *	the specified port.
617 *	Returns FALSE otherwise.
618 *
619 * SYNOPSIS
620 */
621 boolean_t osm_node_has_any_link(IN osm_node_t * p_node, IN uint8_t port_num);
622 /*
623 * PARAMETERS
624 *	p_node
625 *		[in] Pointer to an osm_node_t object.
626 *
627 *	port_num
628 *		[in] Port number in p_node through which to check the link.
629 *
630 * RETURN VALUES
631 *	Return TRUE if a any link exists from the specified nodes on
632 *	the specified port.
633 *	Returns FALSE otherwise.
634 *
635 * NOTES
636 *
637 * SEE ALSO
638 *	Node object
639 *********/
640 
641 /****f* OpenSM: Node/osm_node_link_has_valid_ports
642 * NAME
643 *	osm_node_link_has_valid_ports
644 *
645 * DESCRIPTION
646 *	Return TRUE if both ports in the link are valid (initialized).
647 *	Returns FALSE otherwise.
648 *
649 * SYNOPSIS
650 */
651 boolean_t osm_node_link_has_valid_ports(IN osm_node_t * p_node,
652 					IN uint8_t port_num,
653 					IN osm_node_t * p_remote_node,
654 					IN uint8_t remote_port_num);
655 /*
656 * PARAMETERS
657 *	p_node
658 *		[in] Pointer to an osm_node_t object.
659 *
660 *	port_num
661 *		[in] Port number in p_node through which to check the link.
662 *
663 * RETURN VALUES
664 *	Return TRUE if both ports in the link are valid (initialized).
665 *	Returns FALSE otherwise.
666 *
667 * NOTES
668 *
669 * SEE ALSO
670 *	Node object
671 *********/
672 
673 END_C_DECLS
674 #endif				/* _OSM_NODE_H_ */
675