2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2008 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 * Declaration of osm_switch_t.
39 * This object represents an IBA switch.
40 * This object is part of the OpenSM family of objects.
43 #ifndef _OSM_SWITCH_H_
44 #define _OSM_SWITCH_H_
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>
55 # define BEGIN_C_DECLS extern "C" {
56 # define END_C_DECLS }
57 #else /* !__cplusplus */
58 # define BEGIN_C_DECLS
60 #endif /* __cplusplus */
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.
72 * The Switch object is not thread safe, thus callers must provide
75 * This object should be treated as opaque and should be
76 * manipulated only through the provided functions.
82 /****s* OpenSM: Switch/osm_switch_t
89 * This object should be treated as opaque and should
90 * be manipulated only through the provided functions.
94 typedef struct osm_switch {
95 cl_map_item_t map_item;
97 ib_switch_info_t switch_info;
102 osm_port_profile_t *p_prof;
105 osm_mcast_tbl_t mcast_tbl;
106 uint32_t discovery_count;
107 unsigned need_update;
113 * Linkage structure for cl_qmap. MUST BE FIRST MEMBER!
116 * Pointer to the Node object for this switch.
119 * IBA defined SwitchInfo structure for this switch.
122 * Max LID that is accessible from this switch.
125 * Number of ports for this switch.
128 * Size of hops table for this switch.
131 * LID Matrix for this switch containing the hop count
132 * to every LID from every port.
135 * Pointer to array of Port Profile objects for this switch.
138 * This switch's linear forwarding table.
141 * This switch's linear forwarding table, as was
142 * calculated by the last routing engine execution.
145 * Multicast forwarding table for this switch.
148 * The number of times this switch has been discovered
149 * during the current fabric sweep. This number is reset
150 * to zero at the start of a sweep.
153 * When set indicates that switch was probably reset, so
154 * fwd tables and rest cached data should be flushed
160 /****s* OpenSM: Switch/struct osm_remote_guids_count
162 * struct osm_remote_guids_count
165 * Stores array of pointers to remote node and the numbers of
166 * times a switch has forwarded to it.
170 struct osm_remote_guids_count {
172 struct osm_remote_node {
174 unsigned forwarded_to;
180 * A number of used entries in array.
186 * A count of lids forwarded to this node.
189 /****f* OpenSM: Switch/osm_switch_delete
194 * Destroys and deallocates the object.
198 void osm_switch_delete(IN OUT osm_switch_t ** const pp_sw);
202 * [in] Pointer to the object to destroy.
210 * Switch object, osm_switch_new
213 /****f* OpenSM: Switch/osm_switch_new
218 * The osm_switch_new function initializes a Switch object for use.
222 osm_switch_t *osm_switch_new(IN osm_node_t * const p_node,
223 IN const osm_madw_t * const p_madw);
227 * [in] Pointer to the node object of this switch
230 * [in] Pointer to the MAD Wrapper containing the switch's
231 * SwitchInfo attribute.
234 * Pointer to the new initialized switch object.
239 * Switch object, osm_switch_delete
242 /****f* OpenSM: Switch/osm_switch_get_hop_count
244 * osm_switch_get_hop_count
247 * Returns the hop count at the specified LID/Port intersection.
251 static inline uint8_t
252 osm_switch_get_hop_count(IN const osm_switch_t * const p_sw,
253 IN const uint16_t lid_ho, IN const uint8_t port_num)
255 return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
256 OSM_NO_PATH : p_sw->hops[lid_ho][port_num];
261 * [in] Pointer to a Switch object.
264 * [in] LID value (host order) for which to return the hop count
267 * [in] Port number in the switch
270 * Returns the hop count at the specified LID/Port intersection.
277 /****f* OpenSM: Switch/osm_switch_set_hops
279 * osm_switch_set_hops
282 * Sets the hop count at the specified LID/Port intersection.
287 osm_switch_set_hops(IN osm_switch_t * const p_sw,
288 IN const uint16_t lid_ho,
289 IN const uint8_t port_num, IN const uint8_t num_hops);
293 * [in] Pointer to a Switch object.
296 * [in] LID value (host order) for which to set the count.
299 * [in] port number for which to set the count.
302 * [in] value to assign to this entry.
305 * Returns the hop count at the specified LID/Port intersection.
312 /****f* OpenSM: Switch/osm_switch_clear_hops
314 * osm_switch_clear_hops
317 * Cleanup existing hops tables (lid matrix)
321 void osm_switch_clear_hops(IN osm_switch_t * p_sw);
325 * [in] Pointer to a Switch object.
332 /****f* OpenSM: Switch/osm_switch_get_least_hops
334 * osm_switch_get_least_hops
337 * Returns the number of hops in the short path to this lid from
338 * any port on the switch.
342 static inline uint8_t
343 osm_switch_get_least_hops(IN const osm_switch_t * const p_sw,
344 IN const uint16_t lid_ho)
346 return (lid_ho > p_sw->max_lid_ho || !p_sw->hops[lid_ho]) ?
347 OSM_NO_PATH : p_sw->hops[lid_ho][0];
352 * [in] Pointer to an osm_switch_t object.
355 * [in] LID (host order) for which to retrieve the shortest hop count.
358 * Returns the number of hops in the short path to this lid from
359 * any port on the switch.
367 /****f* OpenSM: Switch/osm_switch_get_port_least_hops
369 * osm_switch_get_port_least_hops
372 * Returns the number of hops in the short path to this port from
373 * any port on the switch.
378 osm_switch_get_port_least_hops(IN const osm_switch_t * const p_sw,
379 IN const osm_port_t * p_port);
383 * [in] Pointer to an osm_switch_t object.
386 * [in] Pointer to an osm_port_t object for which to
387 * retrieve the shortest hop count.
390 * Returns the number of hops in the short path to this lid from
391 * any port on the switch.
399 /****f* OpenSM: Switch/osm_switch_get_port_by_lid
401 * osm_switch_get_port_by_lid
404 * Returns the switch port number on which the specified LID is routed.
408 static inline uint8_t
409 osm_switch_get_port_by_lid(IN const osm_switch_t * const p_sw,
410 IN const uint16_t lid_ho)
412 if (lid_ho == 0 || lid_ho > IB_LID_UCAST_END_HO)
414 return p_sw->lft[lid_ho];
419 * [in] Pointer to an osm_switch_t object.
422 * [in] LID (host order) for which to retrieve the shortest hop count.
425 * Returns the switch port on which the specified LID is routed.
433 /****f* OpenSM: Switch/osm_switch_get_physp_ptr
435 * osm_switch_get_physp_ptr
438 * Gets the Physical Port Object at the specified port number.
442 osm_physp_t *osm_switch_get_physp_ptr(IN const osm_switch_t * const p_sw,
443 IN const uint32_t port_num);
447 * [in] Pointer to an osm_switch_t object.
450 * [in] Port number for which to retrieve the Physical Port Object.
453 * Returns a pointer to the Physical Port Object object at the specified
455 * A return value of zero means the port number was out of range.
464 /****f* OpenSM: Switch/osm_switch_get_route_by_lid
466 * osm_switch_get_route_by_lid
469 * Gets the physical port object that routes the specified LID.
473 static inline osm_physp_t *osm_switch_get_route_by_lid(IN const osm_switch_t *
475 IN const ib_net16_t lid)
482 port_num = osm_switch_get_port_by_lid(p_sw, cl_ntoh16(lid));
485 In order to avoid holes in the subnet (usually happens when
486 running UPDN algorithm), i.e. cases where port is
487 unreachable through a switch (we put an OSM_NO_PATH value at
488 the port entry, we do not assert on unreachable lid entries
489 at the fwd table but return NULL
491 if (port_num != OSM_NO_PATH)
492 return (osm_node_get_physp_ptr(p_sw->p_node, port_num));
499 * [in] Pointer to an osm_switch_t object.
502 * [in] LID for which to find a route. This must be a unicast
503 * LID value < 0xC000.
506 * Returns a pointer to the Physical Port Object object that
507 * routes the specified LID. A return value of zero means
508 * there is no route for the lid through this switch.
509 * The lid value must be a unicast LID.
517 /****f* OpenSM: Switch/osm_switch_sp0_is_lmc_capable
519 * osm_switch_sp0_is_lmc_capable
522 * Returns whether switch port 0 (SP0) can support LMC
525 static inline unsigned
526 osm_switch_sp0_is_lmc_capable(IN const osm_switch_t * const p_sw,
527 IN osm_subn_t * p_subn)
529 return (p_subn->opt.lmc_esp0 &&
530 ib_switch_info_is_enhanced_port0(&p_sw->switch_info)) ? 1 : 0;
535 * [in] Pointer to an osm_switch_t object.
538 * [in] Pointer to an osm_subn_t object.
541 * TRUE if SP0 is enhanced and globally enabled. FALSE otherwise.
544 * This is workaround function, it takes into account user defined
545 * p_subn->opt.lmc_esp0 parameter.
550 /****f* OpenSM: Switch/osm_switch_get_max_block_id_in_use
552 * osm_switch_get_max_block_id_in_use
555 * Returns the maximum block ID (host order) of this switch that
556 * is used for unicast routing.
560 static inline uint16_t
561 osm_switch_get_max_block_id_in_use(IN const osm_switch_t * const p_sw)
563 return cl_ntoh16(p_sw->switch_info.lin_top) / IB_SMP_DATA_SIZE;
568 * [in] Pointer to an osm_switch_t object.
571 * Returns the maximum block ID (host order) of this switch.
579 /****f* OpenSM: Switch/osm_switch_get_lft_block
581 * osm_switch_get_lft_block
584 * Retrieve a linear forwarding table block.
589 osm_switch_get_lft_block(IN const osm_switch_t * const p_sw,
590 IN const uint16_t block_id,
591 OUT uint8_t * const p_block);
595 * [in] Pointer to an osm_switch_t object.
598 * [in] The block_id to retrieve.
601 * [out] Pointer to the 64 byte array to store the
602 * forwarding table clock specified by block_id.
605 * Returns true if there are more blocks necessary to
606 * configure all the LIDs reachable from this switch.
614 /****f* OpenSM: Switch/osm_switch_supports_mcast
616 * osm_switch_supports_mcast
619 * Indicates if a switch supports multicast.
623 static inline boolean_t
624 osm_switch_supports_mcast(IN const osm_switch_t * const p_sw)
626 return (p_sw->switch_info.mcast_cap != 0);
631 * [in] Pointer to an osm_switch_t object.
634 * Returns TRUE if the switch supports multicast.
642 /****f* OpenSM: Switch/osm_switch_set_switch_info
644 * osm_switch_set_switch_info
647 * Updates the switch info attribute of this switch.
652 osm_switch_set_switch_info(IN osm_switch_t * const p_sw,
653 IN const ib_switch_info_t * const p_si)
657 p_sw->switch_info = *p_si;
662 * [in] Pointer to a Switch object.
665 * [in] Pointer to the SwitchInfo attribute for this switch.
675 /****f* OpenSM: Switch/osm_switch_count_path
677 * osm_switch_count_path
680 * Counts this path in port profile.
685 osm_switch_count_path(IN osm_switch_t * const p_sw, IN const uint8_t port)
687 osm_port_prof_path_count_inc(&p_sw->p_prof[port]);
692 * [in] Pointer to the switch object.
695 * [in] Port to count path.
705 /****f* OpenSM: Switch/osm_switch_set_lft_block
707 * osm_switch_set_lft_block
710 * Copies in the specified block into
711 * the switch's Linear Forwarding Table.
715 static inline ib_api_status_t
716 osm_switch_set_lft_block(IN osm_switch_t * const p_sw,
717 IN const uint8_t * const p_block,
718 IN const uint32_t block_num)
721 (uint16_t) (block_num * IB_SMP_DATA_SIZE);
724 if (lid_start + IB_SMP_DATA_SIZE > IB_LID_UCAST_END_HO)
725 return IB_INVALID_PARAMETER;
727 memcpy(&p_sw->lft[lid_start], p_block, IB_SMP_DATA_SIZE);
733 * [in] Pointer to the switch object.
736 * [in] Pointer to the forwarding table block.
739 * [in] Block number for this block
749 /****f* OpenSM: Switch/osm_switch_set_mft_block
751 * osm_switch_set_mft_block
754 * Sets a block of multicast port masks into the multicast table.
758 static inline ib_api_status_t
759 osm_switch_set_mft_block(IN osm_switch_t * const p_sw,
760 IN const ib_net16_t * const p_block,
761 IN const uint16_t block_num, IN const uint8_t position)
764 return (osm_mcast_tbl_set_block(&p_sw->mcast_tbl, p_block,
765 block_num, position));
770 * [in] Pointer to the switch object.
773 * [in] Pointer to the block of port masks to set.
776 * [in] Block number (0-511) to set.
779 * [in] Port mask position (0-15) to set.
782 * IB_SUCCESS on success.
789 /****f* OpenSM: Switch/osm_switch_get_mft_block
791 * osm_switch_get_mft_block
794 * Retrieve a block of multicast port masks from the multicast table.
798 static inline boolean_t
799 osm_switch_get_mft_block(IN osm_switch_t * const p_sw,
800 IN const uint16_t block_num,
801 IN const uint8_t position,
802 OUT ib_net16_t * const p_block)
805 return (osm_mcast_tbl_get_block(&p_sw->mcast_tbl,
806 block_num, position, p_block));
811 * [in] Pointer to the switch object.
814 * [in] Block number (0-511) to set.
817 * [in] Port mask position (0-15) to set.
820 * [out] Pointer to the block of port masks stored.
823 * Returns true if there are more blocks necessary to
824 * configure all the MLIDs reachable from this switch.
832 /****f* OpenSM: Switch/osm_switch_get_mft_max_block
834 * osm_switch_get_mft_max_block
837 * Get the max_block from the associated multicast table.
841 static inline uint16_t
842 osm_switch_get_mft_max_block(IN osm_switch_t * const p_sw)
845 return (osm_mcast_tbl_get_max_block(&p_sw->mcast_tbl));
850 * [in] Pointer to the switch object.
855 /****f* OpenSM: Switch/osm_switch_get_mft_max_block_in_use
857 * osm_switch_get_mft_max_block_in_use
860 * Get the max_block_in_use from the associated multicast table.
864 static inline int16_t
865 osm_switch_get_mft_max_block_in_use(IN osm_switch_t * const p_sw)
868 return (osm_mcast_tbl_get_max_block_in_use(&p_sw->mcast_tbl));
873 * [in] Pointer to the switch object.
876 * Returns the maximum block ID in use in this switch's mcast table.
877 * A value of -1 indicates no blocks are in use.
884 /****f* OpenSM: Switch/osm_switch_get_mft_max_position
886 * osm_switch_get_mft_max_position
889 * Get the max_position from the associated multicast table.
893 static inline uint8_t
894 osm_switch_get_mft_max_position(IN osm_switch_t * const p_sw)
897 return (osm_mcast_tbl_get_max_position(&p_sw->mcast_tbl));
902 * [in] Pointer to the switch object.
907 /****f* OpenSM: Switch/osm_switch_recommend_path
909 * osm_switch_recommend_path
912 * Returns the recommended port on which to route this LID.
913 * In cases where LMC > 0, the remote side system and node
914 * used for the routing are tracked in the provided arrays
915 * (and counts) such that other lid for the same port will
916 * try and avoid going through the same remote system/node.
921 osm_switch_recommend_path(IN const osm_switch_t * const p_sw,
922 IN osm_port_t * p_port,
923 IN const uint16_t lid_ho,
924 IN unsigned start_from,
925 IN const boolean_t ignore_existing,
926 IN const boolean_t dor);
930 * [in] Pointer to the switch object.
933 * [in] Pointer to the port object for which to get a path
937 * [in] LID value (host order) for which to get a path advisory.
940 * [in] Port number from where to start balance counting.
943 * [in] Set to cause the switch to choose the optimal route
944 * regardless of existing paths.
945 * If false, the switch will choose an existing route if one
946 * exists, otherwise will choose the optimal route.
949 * [in] If TRUE, Dimension Order Routing will be done.
952 * Returns the recommended port on which to route this LID.
959 /****f* OpenSM: Switch/osm_switch_recommend_mcast_path
961 * osm_switch_recommend_mcast_path
964 * Returns the recommended port on which to route this LID.
969 osm_switch_recommend_mcast_path(IN osm_switch_t * const p_sw,
970 IN osm_port_t * p_port,
971 IN const uint16_t mlid_ho,
972 IN const boolean_t ignore_existing);
976 * [in] Pointer to the switch object.
979 * [in] Pointer to the port object for which to get
980 * the multicast path.
983 * [in] MLID for the multicast group in question.
986 * [in] Set to cause the switch to choose the optimal route
987 * regardless of existing paths.
988 * If false, the switch will choose an existing route if one exists,
989 * otherwise will choose the optimal route.
992 * Returns the recommended port on which to route this LID.
999 /****f* OpenSM: Switch/osm_switch_get_mcast_fwd_tbl_size
1001 * osm_switch_get_mcast_fwd_tbl_size
1004 * Returns the number of entries available in the multicast forwarding table.
1008 static inline uint16_t
1009 osm_switch_get_mcast_fwd_tbl_size(IN const osm_switch_t * const p_sw)
1011 return (cl_ntoh16(p_sw->switch_info.mcast_cap));
1016 * [in] Pointer to the switch.
1019 * Returns the number of entries available in the multicast forwarding table.
1026 /****f* OpenSM: Switch/osm_switch_path_count_get
1028 * osm_switch_path_count_get
1031 * Returns the count of the number of paths going through this port.
1035 static inline uint32_t
1036 osm_switch_path_count_get(IN const osm_switch_t * const p_sw,
1037 IN const uint8_t port_num)
1039 return (osm_port_prof_path_count_get(&p_sw->p_prof[port_num]));
1044 * [in] Pointer to the Switch object.
1047 * [in] Port number for which to get path count.
1050 * Returns the count of the number of paths going through this port.
1057 /****f* OpenSM: Switch/osm_switch_prepare_path_rebuild
1059 * osm_switch_prepare_path_rebuild
1062 * Prepares a switch to rebuild pathing information.
1067 osm_switch_prepare_path_rebuild(IN osm_switch_t * p_sw, IN uint16_t max_lids);
1071 * [in] Pointer to the Switch object.
1074 * [in] Max number of lids in the subnet.
1077 * Returns zero on success, or negative value if an error occurred.
1084 /****f* OpenSM: Switch/osm_switch_get_mcast_tbl_ptr
1086 * osm_switch_get_mcast_tbl_ptr
1089 * Returns a pointer to the switch's multicast table.
1093 static inline osm_mcast_tbl_t *osm_switch_get_mcast_tbl_ptr(IN const
1097 return ((osm_mcast_tbl_t *) & p_sw->mcast_tbl);
1102 * [in] Pointer to the switch.
1105 * Returns a pointer to the switch's multicast table.
1112 /****f* OpenSM: Switch/osm_switch_is_in_mcast_tree
1114 * osm_switch_is_in_mcast_tree
1117 * Returns true if this switch already belongs in the tree for the specified
1122 static inline boolean_t
1123 osm_switch_is_in_mcast_tree(IN const osm_switch_t * const p_sw,
1124 IN const uint16_t mlid_ho)
1126 const osm_mcast_tbl_t *p_tbl;
1128 p_tbl = &p_sw->mcast_tbl;
1130 return (osm_mcast_tbl_is_any_port(&p_sw->mcast_tbl, mlid_ho));
1137 * [in] Pointer to the switch.
1140 * [in] MLID (host order) of the multicast tree to check.
1143 * Returns true if this switch already belongs in the tree for the specified
1152 #endif /* _OSM_SWITCH_H_ */