1 /*
2  * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2009 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_switch_t.
39  *	This object represents an IBA switch.
40  *	This object is part of the OpenSM family of objects.
41  */
42 
43 #ifndef _OSM_SWITCH_H_
44 #define _OSM_SWITCH_H_
45 
46 #include <iba/ib_types.h>
47 #include <opensm/osm_base.h>
48 #include <opensm/osm_madw.h>
49 #include <opensm/osm_node.h>
50 #include <opensm/osm_port.h>
51 #include <opensm/osm_mcast_tbl.h>
52 #include <opensm/osm_port_profile.h>
53 
54 #ifdef __cplusplus
55 #  define BEGIN_C_DECLS extern "C" {
56 #  define END_C_DECLS   }
57 #else				/* !__cplusplus */
58 #  define BEGIN_C_DECLS
59 #  define END_C_DECLS
60 #endif				/* __cplusplus */
61 
62 BEGIN_C_DECLS
63 /****h* OpenSM/Switch
64 * NAME
65 *	Switch
66 *
67 * DESCRIPTION
68 *	The Switch object encapsulates the information needed by the
69 *	OpenSM to manage switches.  The OpenSM allocates one switch object
70 *	per switch in the IBA subnet.
71 *
72 *	The Switch object is not thread safe, thus callers must provide
73 *	serialization.
74 *
75 *	This object should be treated as opaque and should be
76 *	manipulated only through the provided functions.
77 *
78 * AUTHOR
79 *	Steve King, Intel
80 *
81 *********/
82 /****s* OpenSM: Switch/osm_switch_t
83 * NAME
84 *	osm_switch_t
85 *
86 * DESCRIPTION
87 *	Switch structure.
88 *
89 *	This object should be treated as opaque and should
90 *	be manipulated only through the provided functions.
91 *
92 * SYNOPSIS
93 */
94 typedef struct osm_switch {
95 	cl_map_item_t map_item;
96 	osm_node_t *p_node;
97 	ib_switch_info_t switch_info;
98 	uint16_t max_lid_ho;
99 	uint8_t num_ports;
100 	uint16_t num_hops;
101 	uint8_t **hops;
102 	osm_port_profile_t *p_prof;
103 	uint8_t *search_ordering_ports;
104 	uint8_t *lft;
105 	uint8_t *new_lft;
106 	uint16_t lft_size;
107 	osm_mcast_tbl_t mcast_tbl;
108 	int32_t mft_block_num;
109 	uint32_t mft_position;
110 	unsigned endport_links;
111 	unsigned need_update;
112 	void *priv;
113 	cl_map_item_t mgrp_item;
114 	uint32_t num_of_mcm;
115 	uint8_t is_mc_member;
116 } osm_switch_t;
117 /*
118 * FIELDS
119 *	map_item
120 *		Linkage structure for cl_qmap.  MUST BE FIRST MEMBER!
121 *
122 *	p_node
123 *		Pointer to the Node object for this switch.
124 *
125 *	switch_info
126 *		IBA defined SwitchInfo structure for this switch.
127 *
128 *	max_lid_ho
129 *		Max LID that is accessible from this switch.
130 *
131 *	num_ports
132 *		Number of ports for this switch.
133 *
134 *	num_hops
135 *		Size of hops table for this switch.
136 *
137 *	hops
138 *		LID Matrix for this switch containing the hop count
139 *		to every LID from every port.
140 *
141 *	p_prof
142 *		Pointer to array of Port Profile objects for this switch.
143 *
144 *	lft
145 *		This switch's linear forwarding table.
146 *
147 *	new_lft
148 *		This switch's linear forwarding table, as was
149 *		calculated by the last routing engine execution.
150 *
151 *	mcast_tbl
152 *		Multicast forwarding table for this switch.
153 *
154 *	need_update
155 *		When set indicates that switch was probably reset, so
156 *		fwd tables and rest cached data should be flushed
157 *
158 *	mgrp_item
159 *		map item for switch in building mcast tree
160 *
161 *	num_of_mcm
162 *		number of mcast members(ports) connected to switch
163 *
164 *	is_mc_member
165 *		whether switch is a mcast member itself
166 *
167 * SEE ALSO
168 *	Switch object
169 *********/
170 
171 /****s* OpenSM: Switch/struct osm_remote_guids_count
172 * NAME
173 *	struct osm_remote_guids_count
174 *
175 * DESCRIPTION
176 *	Stores array of pointers to remote node and the numbers of
177 *	times a switch has forwarded to it.
178 *
179 * SYNOPSIS
180 */
181 struct osm_remote_guids_count {
182 	unsigned count;
183 	struct osm_remote_node {
184 		osm_node_t *node;
185 		unsigned forwarded_to;
186 		uint8_t port;
187 	} guids[0];
188 };
189 /*
190 * FIELDS
191 *	count
192 *		A number of used entries in array.
193 *
194 *	node
195 *		A pointer to node.
196 *
197 *	forwarded_to
198 *		A count of lids forwarded to this node.
199 *
200 *	port
201 *		Port number on the node.
202 *********/
203 
204 /****f* OpenSM: Switch/osm_switch_delete
205 * NAME
206 *	osm_switch_delete
207 *
208 * DESCRIPTION
209 *	Destroys and deallocates the object.
210 *
211 * SYNOPSIS
212 */
213 void osm_switch_delete(IN OUT osm_switch_t ** pp_sw);
214 /*
215 * PARAMETERS
216 *	p_sw
217 *		[in] Pointer to the object to destroy.
218 *
219 * RETURN VALUE
220 *	None.
221 *
222 * NOTES
223 *
224 * SEE ALSO
225 *	Switch object, osm_switch_new
226 *********/
227 
228 /****f* OpenSM: Switch/osm_switch_new
229 * NAME
230 *	osm_switch_new
231 *
232 * DESCRIPTION
233 *	The osm_switch_new function initializes a Switch object for use.
234 *
235 * SYNOPSIS
236 */
237 osm_switch_t *osm_switch_new(IN osm_node_t * p_node,
238 			     IN const osm_madw_t * p_madw);
239 /*
240 * PARAMETERS
241 *	p_node
242 *		[in] Pointer to the node object of this switch
243 *
244 *	p_madw
245 *		[in] Pointer to the MAD Wrapper containing the switch's
246 *		SwitchInfo attribute.
247 *
248 * RETURN VALUES
249 *	Pointer to the new initialized switch object.
250 *
251 * NOTES
252 *
253 * SEE ALSO
254 *	Switch object, osm_switch_delete
255 *********/
256 
257 /****f* OpenSM: Switch/osm_switch_get_hop_count
258 * NAME
259 *	osm_switch_get_hop_count
260 *
261 * DESCRIPTION
262 *	Returns the hop count at the specified LID/Port intersection.
263 *
264 * SYNOPSIS
265 */
osm_switch_get_hop_count(IN const osm_switch_t * p_sw,IN uint16_t lid_ho,IN uint8_t port_num)266 static inline uint8_t osm_switch_get_hop_count(IN const osm_switch_t * p_sw,
267 					       IN uint16_t lid_ho,
268 					       IN uint8_t port_num)
269 {
270 	return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
271 	    OSM_NO_PATH : p_sw->hops[lid_ho][port_num];
272 }
273 /*
274 * PARAMETERS
275 *	p_sw
276 *		[in] Pointer to a Switch object.
277 *
278 *	lid_ho
279 *		[in] LID value (host order) for which to return the hop count
280 *
281 *	port_num
282 *		[in] Port number in the switch
283 *
284 * RETURN VALUES
285 *	Returns the hop count at the specified LID/Port intersection.
286 *
287 * NOTES
288 *
289 * SEE ALSO
290 *********/
291 
292 /****f* OpenSM: Switch/osm_switch_set_hops
293 * NAME
294 *	osm_switch_set_hops
295 *
296 * DESCRIPTION
297 *	Sets the hop count at the specified LID/Port intersection.
298 *
299 * SYNOPSIS
300 */
301 cl_status_t osm_switch_set_hops(IN osm_switch_t * p_sw, IN uint16_t lid_ho,
302 				IN uint8_t port_num, IN uint8_t num_hops);
303 /*
304 * PARAMETERS
305 *	p_sw
306 *		[in] Pointer to a Switch object.
307 *
308 *	lid_ho
309 *		[in] LID value (host order) for which to set the count.
310 *
311 *	port_num
312 *		[in] port number for which to set the count.
313 *
314 *	num_hops
315 *		[in] value to assign to this entry.
316 *
317 * RETURN VALUES
318 *	Returns 0 if successful. -1 if it failed
319 *
320 * NOTES
321 *
322 * SEE ALSO
323 *********/
324 
325 /****f* OpenSM: Switch/osm_switch_clear_hops
326 * NAME
327 *	osm_switch_clear_hops
328 *
329 * DESCRIPTION
330 *	Cleanup existing hops tables (lid matrix)
331 *
332 * SYNOPSIS
333 */
334 void osm_switch_clear_hops(IN osm_switch_t * p_sw);
335 /*
336 * PARAMETERS
337 *	p_sw
338 *		[in] Pointer to a Switch object.
339 *
340 * NOTES
341 *
342 * SEE ALSO
343 *********/
344 
345 /****f* OpenSM: Switch/osm_switch_get_least_hops
346 * NAME
347 *	osm_switch_get_least_hops
348 *
349 * DESCRIPTION
350 *	Returns the number of hops in the short path to this lid from
351 *	any port on the switch.
352 *
353 * SYNOPSIS
354 */
osm_switch_get_least_hops(IN const osm_switch_t * p_sw,IN uint16_t lid_ho)355 static inline uint8_t osm_switch_get_least_hops(IN const osm_switch_t * p_sw,
356 						IN uint16_t lid_ho)
357 {
358 	return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
359 	    OSM_NO_PATH : p_sw->hops[lid_ho][0];
360 }
361 /*
362 * PARAMETERS
363 *	p_sw
364 *		[in] Pointer to an osm_switch_t object.
365 *
366 *	lid_ho
367 *		[in] LID (host order) for which to retrieve the shortest hop count.
368 *
369 * RETURN VALUES
370 *	Returns the number of hops in the short path to this lid from
371 *	any port on the switch.
372 *
373 * NOTES
374 *
375 * SEE ALSO
376 *	Switch object
377 *********/
378 
379 /****f* OpenSM: Switch/osm_switch_get_port_least_hops
380 * NAME
381 *	osm_switch_get_port_least_hops
382 *
383 * DESCRIPTION
384 *	Returns the number of hops in the short path to this port from
385 *	any port on the switch.
386 *
387 * SYNOPSIS
388 */
389 uint8_t osm_switch_get_port_least_hops(IN const osm_switch_t * p_sw,
390 				       IN const osm_port_t * p_port);
391 /*
392 * PARAMETERS
393 *	p_sw
394 *		[in] Pointer to an osm_switch_t object.
395 *
396 *	p_port
397 *		[in] Pointer to an osm_port_t object for which to
398 *		retrieve the shortest hop count.
399 *
400 * RETURN VALUES
401 *	Returns the number of hops in the short path to this lid from
402 *	any port on the switch.
403 *
404 * NOTES
405 *
406 * SEE ALSO
407 *	Switch object
408 *********/
409 
410 /****d* OpenSM: osm_lft_type_enum
411 * NAME
412 *	osm_lft_type_enum
413 *
414 * DESCRIPTION
415 *	Enumerates LFT sets types of a switch.
416 *
417 * SYNOPSIS
418 */
419 typedef enum osm_lft_type_enum {
420 	OSM_LFT = 0,
421 	OSM_NEW_LFT
422 } osm_lft_type_enum;
423 /***********/
424 
425 /****f* OpenSM: Switch/osm_switch_get_port_by_lid
426 * NAME
427 *	osm_switch_get_port_by_lid
428 *
429 * DESCRIPTION
430 *	Returns the switch port number on which the specified LID is routed.
431 *
432 * SYNOPSIS
433 */
osm_switch_get_port_by_lid(IN const osm_switch_t * p_sw,IN uint16_t lid_ho,IN osm_lft_type_enum lft_enum)434 static inline uint8_t osm_switch_get_port_by_lid(IN const osm_switch_t * p_sw,
435 						 IN uint16_t lid_ho,
436 						 IN osm_lft_type_enum lft_enum)
437 {
438 	if (lid_ho == 0 || lid_ho > p_sw->max_lid_ho)
439 		return OSM_NO_PATH;
440 	return lft_enum == OSM_LFT ? p_sw->lft[lid_ho] : p_sw->new_lft[lid_ho];
441 }
442 /*
443 * PARAMETERS
444 *	p_sw
445 *		[in] Pointer to an osm_switch_t object.
446 *
447 *	lid_ho
448 *		[in] LID (host order) for which to retrieve the shortest hop count.
449 *
450 *	lft_enum
451 *		[in] Use LFT that was calculated by routing engine, or
452 *		current LFT on the switch.
453 *
454 * RETURN VALUES
455 *	Returns the switch port on which the specified LID is routed.
456 *
457 * NOTES
458 *
459 * SEE ALSO
460 *	Switch object
461 *********/
462 
463 /****f* OpenSM: Switch/osm_switch_get_route_by_lid
464 * NAME
465 *	osm_switch_get_route_by_lid
466 *
467 * DESCRIPTION
468 *	Gets the physical port object that routes the specified LID.
469 *
470 * SYNOPSIS
471 */
osm_switch_get_route_by_lid(IN const osm_switch_t * p_sw,IN ib_net16_t lid)472 static inline osm_physp_t *osm_switch_get_route_by_lid(IN const osm_switch_t *
473 						       p_sw, IN ib_net16_t lid)
474 {
475 	uint8_t port_num;
476 
477 	CL_ASSERT(p_sw);
478 	CL_ASSERT(lid);
479 
480 	port_num = osm_switch_get_port_by_lid(p_sw, cl_ntoh16(lid),
481 					      OSM_NEW_LFT);
482 
483 	/*
484 	   In order to avoid holes in the subnet (usually happens when
485 	   running UPDN algorithm), i.e. cases where port is
486 	   unreachable through a switch (we put an OSM_NO_PATH value at
487 	   the port entry, we do not assert on unreachable lid entries
488 	   at the fwd table but return NULL
489 	 */
490 	if (port_num != OSM_NO_PATH)
491 		return (osm_node_get_physp_ptr(p_sw->p_node, port_num));
492 	else
493 		return NULL;
494 }
495 /*
496 * PARAMETERS
497 *	p_sw
498 *		[in] Pointer to an osm_switch_t object.
499 *
500 *	lid
501 *		[in] LID for which to find a route.  This must be a unicast
502 *		LID value < 0xC000.
503 *
504 * RETURN VALUES
505 *	Returns a pointer to the Physical Port Object object that
506 *	routes the specified LID.  A return value of zero means
507 *	there is no route for the lid through this switch.
508 *	The lid value must be a unicast LID.
509 *
510 * NOTES
511 *
512 * SEE ALSO
513 *	Switch object
514 *********/
515 
516 /****f* OpenSM: Switch/osm_switch_sp0_is_lmc_capable
517 * NAME
518 *	osm_switch_sp0_is_lmc_capable
519 *
520 * DESCRIPTION
521 *	Returns whether switch port 0 (SP0) can support LMC
522 *
523 */
524 static inline unsigned
osm_switch_sp0_is_lmc_capable(IN const osm_switch_t * p_sw,IN osm_subn_t * p_subn)525 osm_switch_sp0_is_lmc_capable(IN const osm_switch_t * p_sw,
526 			      IN osm_subn_t * p_subn)
527 {
528 	return (p_subn->opt.lmc_esp0 &&
529 		ib_switch_info_is_enhanced_port0(&p_sw->switch_info)) ? 1 : 0;
530 }
531 /*
532 * PARAMETERS
533 *	p_sw
534 *		[in] Pointer to an osm_switch_t object.
535 *
536 *	p_subn
537 *		[in] Pointer to an osm_subn_t object.
538 *
539 * RETURN VALUES
540 *	TRUE if SP0 is enhanced and globally enabled. FALSE otherwise.
541 *
542 * NOTES
543 *	This is workaround function, it takes into account user defined
544 *	p_subn->opt.lmc_esp0 parameter.
545 *
546 * SEE ALSO
547 *********/
548 
549 /****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use
550 * NAME
551 *	osm_switch_get_max_block_id_in_use
552 *
553 * DESCRIPTION
554 *	Returns the maximum block ID (host order) of this switch that
555 *	is used for unicast routing.
556 *
557 * SYNOPSIS
558 */
559 static inline uint16_t
osm_switch_get_max_block_id_in_use(IN const osm_switch_t * p_sw)560 osm_switch_get_max_block_id_in_use(IN const osm_switch_t * p_sw)
561 {
562 	return cl_ntoh16(p_sw->switch_info.lin_top) / IB_SMP_DATA_SIZE;
563 }
564 /*
565 * PARAMETERS
566 *	p_sw
567 *		[in] Pointer to an osm_switch_t object.
568 *
569 * RETURN VALUES
570 *	Returns the maximum block ID (host order) of this switch.
571 *
572 * NOTES
573 *
574 * SEE ALSO
575 *	Switch object
576 *********/
577 
578 /****f* OpenSM: Switch/osm_switch_get_lft_block
579 * NAME
580 *	osm_switch_get_lft_block
581 *
582 * DESCRIPTION
583 *	Retrieve a linear forwarding table block.
584 *
585 * SYNOPSIS
586 */
587 boolean_t osm_switch_get_lft_block(IN const osm_switch_t * p_sw,
588 				   IN uint16_t block_id, OUT uint8_t * p_block);
589 /*
590 * PARAMETERS
591 *	p_sw
592 *		[in] Pointer to an osm_switch_t object.
593 *
594 *	block_id
595 *		[in] The block_id to retrieve.
596 *
597 *	p_block
598 *		[out] Pointer to the 64 byte array to store the
599 *		forwarding table block specified by block_id.
600 *
601 * RETURN VALUES
602 *	Returns true if there are more blocks necessary to
603 *	configure all the LIDs reachable from this switch.
604 *	FALSE otherwise.
605 *
606 * NOTES
607 *
608 * SEE ALSO
609 *********/
610 
611 /****f* OpenSM: Switch/osm_switch_supports_mcast
612 * NAME
613 *	osm_switch_supports_mcast
614 *
615 * DESCRIPTION
616 *	Indicates if a switch supports multicast.
617 *
618 * SYNOPSIS
619 */
osm_switch_supports_mcast(IN const osm_switch_t * p_sw)620 static inline boolean_t osm_switch_supports_mcast(IN const osm_switch_t * p_sw)
621 {
622 	return (p_sw->switch_info.mcast_cap != 0);
623 }
624 /*
625 * PARAMETERS
626 *	p_sw
627 *		[in] Pointer to an osm_switch_t object.
628 *
629 * RETURN VALUES
630 *	Returns TRUE if the switch supports multicast.
631 *	FALSE otherwise.
632 *
633 * NOTES
634 *
635 * SEE ALSO
636 *********/
637 
638 /****f* OpenSM: Switch/osm_switch_set_switch_info
639 * NAME
640 *	osm_switch_set_switch_info
641 *
642 * DESCRIPTION
643 *	Updates the switch info attribute of this switch.
644 *
645 * SYNOPSIS
646 */
osm_switch_set_switch_info(IN osm_switch_t * p_sw,IN const ib_switch_info_t * p_si)647 static inline void osm_switch_set_switch_info(IN osm_switch_t * p_sw,
648 					      IN const ib_switch_info_t * p_si)
649 {
650 	CL_ASSERT(p_sw);
651 	CL_ASSERT(p_si);
652 	p_sw->switch_info = *p_si;
653 }
654 /*
655 * PARAMETERS
656 *	p_sw
657 *		[in] Pointer to a Switch object.
658 *
659 *	p_si
660 *		[in] Pointer to the SwitchInfo attribute for this switch.
661 *
662 * RETURN VALUES
663 *	None.
664 *
665 * NOTES
666 *
667 * SEE ALSO
668 *********/
669 
670 /****f* OpenSM: Switch/osm_switch_count_path
671 * NAME
672 *	osm_switch_count_path
673 *
674 * DESCRIPTION
675 *	Counts this path in port profile.
676 *
677 * SYNOPSIS
678 */
osm_switch_count_path(IN osm_switch_t * p_sw,IN uint8_t port)679 static inline void osm_switch_count_path(IN osm_switch_t * p_sw,
680 					 IN uint8_t port)
681 {
682 	osm_port_prof_path_count_inc(&p_sw->p_prof[port]);
683 }
684 /*
685 * PARAMETERS
686 *	p_sw
687 *		[in] Pointer to the switch object.
688 *
689 *	port
690 *		[in] Port to count path.
691 *
692 * RETURN VALUE
693 *	None.
694 *
695 * NOTES
696 *
697 * SEE ALSO
698 *********/
699 
700 /****f* OpenSM: Switch/osm_switch_set_lft_block
701 * NAME
702 *	osm_switch_set_lft_block
703 *
704 * DESCRIPTION
705 *	Copies in the specified block into
706 *	the switch's Linear Forwarding Table.
707 *
708 * SYNOPSIS
709 */
710 static inline ib_api_status_t
osm_switch_set_lft_block(IN osm_switch_t * p_sw,IN const uint8_t * p_block,IN uint32_t block_num)711 osm_switch_set_lft_block(IN osm_switch_t * p_sw, IN const uint8_t * p_block,
712 			 IN uint32_t block_num)
713 {
714 	uint16_t lid_start =
715 		(uint16_t) (block_num * IB_SMP_DATA_SIZE);
716 	CL_ASSERT(p_sw);
717 
718 	if (lid_start + IB_SMP_DATA_SIZE > p_sw->lft_size)
719 		return IB_INVALID_PARAMETER;
720 
721 	memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
722 	return IB_SUCCESS;
723 }
724 /*
725 * PARAMETERS
726 *	p_sw
727 *		[in] Pointer to the switch object.
728 *
729 *	p_block
730 *		[in] Pointer to the forwarding table block.
731 *
732 *	block_num
733 *		[in] Block number for this block
734 *
735 * RETURN VALUE
736 *	None.
737 *
738 * NOTES
739 *
740 * SEE ALSO
741 *********/
742 
743 /****f* OpenSM: Switch/osm_switch_set_mft_block
744 * NAME
745 *	osm_switch_set_mft_block
746 *
747 * DESCRIPTION
748 *	Sets a block of multicast port masks into the multicast table.
749 *
750 * SYNOPSIS
751 */
752 static inline ib_api_status_t
osm_switch_set_mft_block(IN osm_switch_t * p_sw,IN const ib_net16_t * p_block,IN uint16_t block_num,IN uint8_t position)753 osm_switch_set_mft_block(IN osm_switch_t * p_sw, IN const ib_net16_t * p_block,
754 			 IN uint16_t block_num, IN uint8_t position)
755 {
756 	CL_ASSERT(p_sw);
757 	return osm_mcast_tbl_set_block(&p_sw->mcast_tbl, p_block, block_num,
758 				       position);
759 }
760 /*
761 * PARAMETERS
762 *	p_sw
763 *		[in] Pointer to the switch object.
764 *
765 *	p_block
766 *		[in] Pointer to the block of port masks to set.
767 *
768 *	block_num
769 *		[in] Block number (0-511) to set.
770 *
771 *	position
772 *		[in] Port mask position (0-15) to set.
773 *
774 * RETURN VALUE
775 *	IB_SUCCESS on success.
776 *
777 * NOTES
778 *
779 * SEE ALSO
780 *********/
781 
782 /****f* OpenSM: Switch/osm_switch_get_mft_block
783 * NAME
784 *	osm_switch_get_mft_block
785 *
786 * DESCRIPTION
787 *	Retrieve a block of multicast port masks from the multicast table.
788 *
789 * SYNOPSIS
790 */
osm_switch_get_mft_block(IN osm_switch_t * p_sw,IN uint16_t block_num,IN uint8_t position,OUT ib_net16_t * p_block)791 static inline boolean_t osm_switch_get_mft_block(IN osm_switch_t * p_sw,
792 						 IN uint16_t block_num,
793 						 IN uint8_t position,
794 						 OUT ib_net16_t * p_block)
795 {
796 	CL_ASSERT(p_sw);
797 	return osm_mcast_tbl_get_block(&p_sw->mcast_tbl, block_num, position,
798 				       p_block);
799 }
800 /*
801 * PARAMETERS
802 *	p_sw
803 *		[in] Pointer to the switch object.
804 *
805 *	block_num
806 *		[in] Block number (0-511) to set.
807 *
808 *	position
809 *		[in] Port mask position (0-15) to set.
810 *
811 *	p_block
812 *		[out] Pointer to the block of port masks stored.
813 *
814 * RETURN VALUES
815 *	Returns true if there are more blocks necessary to
816 *	configure all the MLIDs reachable from this switch.
817 *	FALSE otherwise.
818 *
819 * NOTES
820 *
821 * SEE ALSO
822 *********/
823 
824 /****f* OpenSM: Switch/osm_switch_get_mft_max_block
825 * NAME
826 *	osm_switch_get_mft_max_block
827 *
828 * DESCRIPTION
829 *       Get the max_block from the associated multicast table.
830 *
831 * SYNOPSIS
832 */
osm_switch_get_mft_max_block(IN osm_switch_t * p_sw)833 static inline uint16_t osm_switch_get_mft_max_block(IN osm_switch_t * p_sw)
834 {
835 	CL_ASSERT(p_sw);
836 	return osm_mcast_tbl_get_max_block(&p_sw->mcast_tbl);
837 }
838 /*
839 * PARAMETERS
840 *	p_sw
841 *		[in] Pointer to the switch object.
842 *
843 * RETURN VALUE
844 */
845 
846 /****f* OpenSM: Switch/osm_switch_get_mft_max_block_in_use
847 * NAME
848 *	osm_switch_get_mft_max_block_in_use
849 *
850 * DESCRIPTION
851 *	Get the max_block_in_use from the associated multicast table.
852 *
853 * SYNOPSIS
854 */
osm_switch_get_mft_max_block_in_use(IN osm_switch_t * p_sw)855 static inline int16_t osm_switch_get_mft_max_block_in_use(IN osm_switch_t * p_sw)
856 {
857 	CL_ASSERT(p_sw);
858 	return osm_mcast_tbl_get_max_block_in_use(&p_sw->mcast_tbl);
859 }
860 /*
861 * PARAMETERS
862 *	p_sw
863 *		[in] Pointer to the switch object.
864 *
865 * RETURN VALUES
866 *	Returns the maximum block ID in use in this switch's mcast table.
867 *	A value of -1 indicates no blocks are in use.
868 *
869 * NOTES
870 *
871 * SEE ALSO
872 */
873 
874 /****f* OpenSM: Switch/osm_switch_get_mft_max_position
875 * NAME
876 *	osm_switch_get_mft_max_position
877 *
878 * DESCRIPTION
879 *       Get the max_position from the associated multicast table.
880 *
881 * SYNOPSIS
882 */
osm_switch_get_mft_max_position(IN osm_switch_t * p_sw)883 static inline uint8_t osm_switch_get_mft_max_position(IN osm_switch_t * p_sw)
884 {
885 	CL_ASSERT(p_sw);
886 	return osm_mcast_tbl_get_max_position(&p_sw->mcast_tbl);
887 }
888 /*
889 * PARAMETERS
890 *	p_sw
891 *		[in] Pointer to the switch object.
892 *
893 * RETURN VALUE
894 */
895 
896 /****f* OpenSM: Switch/osm_switch_get_dimn_port
897 * NAME
898 *	osm_switch_get_dimn_port
899 *
900 * DESCRIPTION
901 *	Get the routing ordered port
902 *
903 * SYNOPSIS
904 */
osm_switch_get_dimn_port(IN const osm_switch_t * p_sw,IN uint8_t port_num)905 static inline uint8_t osm_switch_get_dimn_port(IN const osm_switch_t * p_sw,
906 					       IN uint8_t port_num)
907 {
908 	CL_ASSERT(p_sw);
909 	if (p_sw->search_ordering_ports == NULL)
910 		return port_num;
911 	return p_sw->search_ordering_ports[port_num];
912 }
913 /*
914 * PARAMETERS
915 *	p_sw
916 *		[in] Pointer to the switch object.
917 *
918 *	port_num
919 *		[in] Port number in the switch
920 *
921 * RETURN VALUES
922 *	Returns the port number ordered for routing purposes.
923 */
924 
925 /****f* OpenSM: Switch/osm_switch_recommend_path
926 * NAME
927 *	osm_switch_recommend_path
928 *
929 * DESCRIPTION
930 *	Returns the recommended port on which to route this LID.
931 *	In cases where LMC > 0, the remote side system and node
932 *	used for the routing are tracked in the provided arrays
933 *	(and counts) such that other lid for the same port will
934 *	try and avoid going through the same remote system/node.
935 *
936 * SYNOPSIS
937 */
938 uint8_t osm_switch_recommend_path(IN const osm_switch_t * p_sw,
939 				  IN osm_port_t * p_port, IN uint16_t lid_ho,
940 				  IN unsigned start_from,
941 				  IN boolean_t ignore_existing,
942 				  IN boolean_t routing_for_lmc,
943 				  IN boolean_t dor,
944 				  IN boolean_t port_shifting,
945 				  IN uint32_t scatter_ports,
946 				  IN osm_lft_type_enum lft_enum);
947 /*
948 * PARAMETERS
949 *	p_sw
950 *		[in] Pointer to the switch object.
951 *
952 *	p_port
953 *		[in] Pointer to the port object for which to get a path
954 *		advisory.
955 *
956 *	lid_ho
957 *		[in] LID value (host order) for which to get a path advisory.
958 *
959 *	start_from
960 *		[in] Port number from where to start balance counting.
961 *
962 *	ignore_existing
963 *		[in] Set to cause the switch to choose the optimal route
964 *		regardless of existing paths.
965 *		If false, the switch will choose an existing route if one
966 *		exists, otherwise will choose the optimal route.
967 *
968 *	routing_for_lmc
969 *		[in] We support an enhanced LMC aware routing mode:
970 *		In the case of LMC > 0, we can track the remote side
971 *		system and node for all of the lids of the target
972 *		and try and avoid routing again through the same
973 *		system / node.
974 *
975 *		Assume if routing_for_lmc is TRUE that this procedure
976 *		was provided with the tracking array and counter via
977 *		p_port->priv, and we can conduct this algorithm.
978 *
979 *	dor
980 *		[in] If TRUE, Dimension Order Routing will be done.
981 *
982 *	port_shifting
983 *		[in] If TRUE, port_shifting will be done.
984 *
985 * 	scatter_ports
986 * 		[in] If not zero, randomize the selection of the best ports.
987 *
988 * 	lft_enum
989 *		[in] Use LFT that was calculated by routing engine, or
990 *		current LFT on the switch.
991 *
992 * RETURN VALUE
993 *	Returns the recommended port on which to route this LID.
994 *
995 * NOTES
996 *
997 * SEE ALSO
998 *********/
999 
1000 /****f* OpenSM: Switch/osm_switch_recommend_mcast_path
1001 * NAME
1002 *	osm_switch_recommend_mcast_path
1003 *
1004 * DESCRIPTION
1005 *	Returns the recommended port on which to route this LID.
1006 *
1007 * SYNOPSIS
1008 */
1009 uint8_t osm_switch_recommend_mcast_path(IN osm_switch_t * p_sw,
1010 					IN osm_port_t * p_port,
1011 					IN uint16_t mlid_ho,
1012 					IN boolean_t ignore_existing);
1013 /*
1014 * PARAMETERS
1015 *	p_sw
1016 *		[in] Pointer to the switch object.
1017 *
1018 *	p_port
1019 *		[in] Pointer to the port object for which to get
1020 *		the multicast path.
1021 *
1022 *	mlid_ho
1023 *		[in] MLID for the multicast group in question.
1024 *
1025 *	ignore_existing
1026 *		[in] Set to cause the switch to choose the optimal route
1027 *		regardless of existing paths.
1028 *		If false, the switch will choose an existing route if one exists,
1029 *		otherwise will choose the optimal route.
1030 *
1031 * RETURN VALUE
1032 *	Returns the recommended port on which to route this LID.
1033 *
1034 * NOTES
1035 *
1036 * SEE ALSO
1037 *********/
1038 
1039 /****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size
1040 * NAME
1041 *	osm_switch_get_mcast_fwd_tbl_size
1042 *
1043 * DESCRIPTION
1044 *	Returns the number of entries available in the multicast forwarding table.
1045 *
1046 * SYNOPSIS
1047 */
1048 static inline uint16_t
osm_switch_get_mcast_fwd_tbl_size(IN const osm_switch_t * p_sw)1049 osm_switch_get_mcast_fwd_tbl_size(IN const osm_switch_t * p_sw)
1050 {
1051 	return cl_ntoh16(p_sw->switch_info.mcast_cap);
1052 }
1053 /*
1054 * PARAMETERS
1055 *	p_sw
1056 *		[in] Pointer to the switch.
1057 *
1058 * RETURN VALUE
1059 *	Returns the number of entries available in the multicast forwarding table.
1060 *
1061 * NOTES
1062 *
1063 * SEE ALSO
1064 *********/
1065 
1066 /****f* OpenSM: Switch/osm_switch_path_count_get
1067 * NAME
1068 *	osm_switch_path_count_get
1069 *
1070 * DESCRIPTION
1071 *	Returns the count of the number of paths going through this port.
1072 *
1073 * SYNOPSIS
1074 */
osm_switch_path_count_get(IN const osm_switch_t * p_sw,IN uint8_t port_num)1075 static inline uint32_t osm_switch_path_count_get(IN const osm_switch_t * p_sw,
1076 						 IN uint8_t port_num)
1077 {
1078 	return osm_port_prof_path_count_get(&p_sw->p_prof[port_num]);
1079 }
1080 /*
1081 * PARAMETERS
1082 *	p_sw
1083 *		[in] Pointer to the Switch object.
1084 *
1085 *	port_num
1086 *		[in] Port number for which to get path count.
1087 *
1088 * RETURN VALUE
1089 *	Returns the count of the number of paths going through this port.
1090 *
1091 * NOTES
1092 *
1093 * SEE ALSO
1094 *********/
1095 
1096 /****f* OpenSM: Switch/osm_switch_prepare_path_rebuild
1097 * NAME
1098 *	osm_switch_prepare_path_rebuild
1099 *
1100 * DESCRIPTION
1101 *	Prepares a switch to rebuild pathing information.
1102 *
1103 * SYNOPSIS
1104 */
1105 int osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw,
1106 				    IN uint16_t max_lids);
1107 /*
1108 * PARAMETERS
1109 *	p_sw
1110 *		[in] Pointer to the Switch object.
1111 *
1112 *	max_lids
1113 *		[in] Max number of lids in the subnet.
1114 *
1115 * RETURN VALUE
1116 *	Returns zero on success, or negative value if an error occurred.
1117 *
1118 * NOTES
1119 *
1120 * SEE ALSO
1121 *********/
1122 
1123 /****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr
1124 * NAME
1125 *	osm_switch_get_mcast_tbl_ptr
1126 *
1127 * DESCRIPTION
1128 *	Returns a pointer to the switch's multicast table.
1129 *
1130 * SYNOPSIS
1131 */
osm_switch_get_mcast_tbl_ptr(IN const osm_switch_t * p_sw)1132 static inline osm_mcast_tbl_t *osm_switch_get_mcast_tbl_ptr(IN const
1133 							    osm_switch_t * p_sw)
1134 {
1135 	return (osm_mcast_tbl_t *) & p_sw->mcast_tbl;
1136 }
1137 /*
1138 * PARAMETERS
1139 *	p_sw
1140 *		[in] Pointer to the switch.
1141 *
1142 * RETURN VALUE
1143 *	Returns a pointer to the switch's multicast table.
1144 *
1145 * NOTES
1146 *
1147 * SEE ALSO
1148 *********/
1149 
1150 /****f* OpenSM: Switch/osm_switch_is_in_mcast_tree
1151 * NAME
1152 *	osm_switch_is_in_mcast_tree
1153 *
1154 * DESCRIPTION
1155 *	Returns true if this switch already belongs in the tree for the specified
1156 *	multicast group.
1157 *
1158 * SYNOPSIS
1159 */
1160 static inline boolean_t
osm_switch_is_in_mcast_tree(IN const osm_switch_t * p_sw,IN uint16_t mlid_ho)1161 osm_switch_is_in_mcast_tree(IN const osm_switch_t * p_sw, IN uint16_t mlid_ho)
1162 {
1163 	const osm_mcast_tbl_t *p_tbl;
1164 
1165 	p_tbl = &p_sw->mcast_tbl;
1166 	if (p_tbl)
1167 		return osm_mcast_tbl_is_any_port(&p_sw->mcast_tbl, mlid_ho);
1168 	else
1169 		return FALSE;
1170 }
1171 /*
1172 * PARAMETERS
1173 *	p_sw
1174 *		[in] Pointer to the switch.
1175 *
1176 *	mlid_ho
1177 *		[in] MLID (host order) of the multicast tree to check.
1178 *
1179 * RETURN VALUE
1180 *	Returns true if this switch already belongs in the tree for the specified
1181 *	multicast group.
1182 *
1183 * NOTES
1184 *
1185 * SEE ALSO
1186 *********/
1187 
1188 END_C_DECLS
1189 #endif				/* _OSM_SWITCH_H_ */
1190