1 /*
2  * Copyright (C) by Argonne National Laboratory
3  *     See COPYRIGHT in top-level directory
4  */
5 
6 /*
7 === BEGIN_MPI_T_CVAR_INFO_BLOCK ===
8 
9 cvars:
10     - name        : MPIR_CVAR_NETLOC_NODE_FILE
11       category    : DEBUGGER
12       type        : string
13       default     : auto
14       class       : none
15       verbosity   : MPI_T_VERBOSITY_USER_BASIC
16       scope       : MPI_T_SCOPE_LOCAL
17       description : >-
18         Subnet json file
19 
20 === END_MPI_T_CVAR_INFO_BLOCK ===
21 */
22 
23 #include "mpiimpl.h"
24 
25 #ifdef HAVE_NETLOC
26 #include "mpir_netloc.h"
27 #endif
28 
29 #ifdef HAVE_NETLOC
30 static netloc_topology_t netloc_topology;
31 static MPIR_Netloc_network_attributes network_attr;
32 #endif
33 
34 #ifdef HAVE_NETLOC
get_nettopo_type(netloc_node_type_t type)35 static MPIR_nettopo_type_e get_nettopo_type(netloc_node_type_t type)
36 {
37     MPIR_nettopo_type_e ret;
38 
39     switch (type) {
40         case NETLOC_NODE_TYPE_HOST:
41             ret = MPIR_NETTOPO_NODE_TYPE__HOST;
42             break;
43         case NETLOC_NODE_TYPE_SWITCH:
44             ret = MPIR_NETTOPO_NODE_TYPE__SWITCH;
45             break;
46         case NETLOC_NODE_TYPE_INVALID:
47             ret = MPIR_NETTOPO_NODE_TYPE__INVALID;
48             break;
49         default:
50             ret = -1;
51     }
52 
53     return ret;
54 }
55 #endif
56 
MPII_nettopo_init(void)57 int MPII_nettopo_init(void)
58 {
59     int mpi_errno = MPI_SUCCESS;
60 
61 #ifdef HAVE_NETLOC
62     network_attr.u.tree.node_levels = NULL;
63     network_attr.network_endpoint = NULL;
64     netloc_topology = NULL;
65     network_attr.type = MPIR_NETTOPO_TYPE__INVALID;
66     if (strlen(MPIR_CVAR_NETLOC_NODE_FILE)) {
67         mpi_errno = netloc_parse_topology(&netloc_topology, MPIR_CVAR_NETLOC_NODE_FILE);
68         if (mpi_errno == NETLOC_SUCCESS)
69             MPIR_Netloc_parse_topology(hwloc_topology, netloc_topology, &network_attr);
70     }
71 #endif
72 
73     return mpi_errno;
74 }
75 
MPII_nettopo_finalize(void)76 int MPII_nettopo_finalize(void)
77 {
78     int mpi_errno = MPI_SUCCESS;
79 
80 #ifdef HAVE_NETLOC
81     switch (network_attr.type) {
82         case MPIR_NETTOPO_TYPE__TORUS:
83             if (network_attr.u.torus.geometry != NULL)
84                 MPL_free(network_attr.u.torus.geometry);
85             break;
86         case MPIR_NETTOPO_TYPE__FAT_TREE:
87         case MPIR_NETTOPO_TYPE__CLOS_NETWORK:
88         default:
89             if (network_attr.u.tree.node_levels != NULL)
90                 MPL_free(network_attr.u.tree.node_levels);
91             break;
92     }
93 #endif
94 
95     return mpi_errno;
96 }
97 
MPIR_nettopo_get_type(void)98 MPIR_nettopo_type_e MPIR_nettopo_get_type(void)
99 {
100     MPIR_nettopo_type_e type = MPIR_NETTOPO_TYPE__INVALID;
101 
102 #ifdef HAVE_NETLOC
103     type = network_attr.type;
104 #endif
105 
106     return type;
107 }
108 
MPIR_nettopo_get_node_type(MPIR_nettopo_node_t node)109 MPIR_nettopo_node_type_e MPIR_nettopo_get_node_type(MPIR_nettopo_node_t node)
110 {
111     MPIR_nettopo_node_type_e type = MPIR_NETTOPO_NODE_TYPE__INVALID;
112 
113     if (node == NULL)
114         return type;
115 
116 #ifdef HAVE_NETLOC
117     type = get_nettopo_type(((netloc_node_t *) node)->node_type);
118 #endif
119 
120     return type;
121 }
122 
MPIR_nettopo_get_endpoint(void)123 MPIR_nettopo_node_t MPIR_nettopo_get_endpoint(void)
124 {
125     MPIR_nettopo_node_t node = NULL;
126 
127 #ifdef HAVE_NETLOC
128     node = network_attr.network_endpoint;
129 #endif
130 
131     return node;
132 }
133 
MPIR_nettopo_get_edge_dest_node(MPIR_nettopo_edge_t edge)134 MPIR_nettopo_node_t MPIR_nettopo_get_edge_dest_node(MPIR_nettopo_edge_t edge)
135 {
136     MPIR_nettopo_node_t node = NULL;
137 
138     if (edge == NULL)
139         return node;
140 
141 #ifdef HAVE_NETLOC
142     node = ((netloc_edge_t *) edge)->dest_node;
143 #endif
144 
145     return node;
146 }
147 
MPIR_nettopo_get_node_uid(MPIR_nettopo_node_t node)148 int MPIR_nettopo_get_node_uid(MPIR_nettopo_node_t node)
149 {
150     int uid = -1;
151 
152     if (node == NULL)
153         return uid;
154 
155 #ifdef HAVE_NETLOC
156     uid = ((netloc_node_t *) node)->__uid__;
157 #endif
158 
159     return uid;
160 }
161 
MPIR_nettopo_get_num_nodes(void)162 int MPIR_nettopo_get_num_nodes(void)
163 {
164     int nodes = 0;
165 
166 #ifdef HAVE_NETLOC
167     nodes = netloc_topology->num_nodes;
168 #endif
169 
170     return nodes;
171 }
172 
MPIR_nettopo_get_all_edges(MPIR_nettopo_node_t node,int * num_edges,MPIR_nettopo_edge_t ** edges)173 int MPIR_nettopo_get_all_edges(MPIR_nettopo_node_t node, int *num_edges,
174                                MPIR_nettopo_edge_t ** edges)
175 {
176     int mpi_errno = MPI_SUCCESS;
177 
178     *num_edges = 0;
179     *edges = NULL;
180 
181     if (node == NULL)
182         return MPI_ERR_OTHER;
183 
184 #ifdef HAVE_NETLOC
185     mpi_errno = netloc_get_all_edges(netloc_topology, node, num_edges, (netloc_edge_t ***) edges);
186 #endif
187 
188     return mpi_errno;
189 }
190 
MPIR_nettopo_tree_get_node_levels(void)191 int *MPIR_nettopo_tree_get_node_levels(void)
192 {
193     int *levels = NULL;
194 
195 #ifdef HAVE_NETLOC
196     levels = network_attr.u.tree.node_levels;
197 #endif
198 
199     return levels;
200 }
201 
MPIR_nettopo_tree_get_hostnode_index(int * node_index,int * num_nodes)202 int MPIR_nettopo_tree_get_hostnode_index(int *node_index, int *num_nodes)
203 {
204     int mpi_errno = MPI_SUCCESS;
205 
206     *node_index = 0;
207     *num_nodes = 0;
208 
209 #ifdef HAVE_NETLOC
210     mpi_errno =
211         MPIR_Netloc_get_hostnode_index_in_tree(network_attr, netloc_topology,
212                                                network_attr.network_endpoint, node_index,
213                                                num_nodes);
214 #endif
215 
216     return mpi_errno;
217 }
218 
MPIR_nettopo_tree_get_switches_at_level(int switch_level,MPIR_nettopo_node_t ** switches_at_level,int * switch_count)219 int MPIR_nettopo_tree_get_switches_at_level(int switch_level,
220                                             MPIR_nettopo_node_t ** switches_at_level,
221                                             int *switch_count)
222 {
223     int mpi_errno = MPI_SUCCESS;
224 
225     *switches_at_level = NULL;
226     *switch_count = 0;
227 
228 #ifdef HAVE_NETLOC
229     mpi_errno =
230         MPIR_Netloc_get_switches_at_level(netloc_topology, network_attr,
231                                           switch_level, (netloc_node_t ***) switches_at_level,
232                                           switch_count);
233 #endif
234 
235     return mpi_errno;
236 }
237 
MPIR_nettopo_torus_get_dimension(void)238 int MPIR_nettopo_torus_get_dimension(void)
239 {
240     int dim = 0;
241 
242 #ifdef HAVE_NETLOC
243     dim = network_attr.u.torus.dimension;
244 #endif
245 
246     return dim;
247 }
248 
MPIR_nettopo_torus_get_geometry(void)249 int *MPIR_nettopo_torus_get_geometry(void)
250 {
251     int *geometry = NULL;
252 
253 #ifdef HAVE_NETLOC
254     geometry = network_attr.u.torus.geometry;
255 #endif
256 
257     return geometry;
258 }
259 
MPIR_nettopo_torus_get_node_index(void)260 int MPIR_nettopo_torus_get_node_index(void)
261 {
262     int idx = 0;
263 
264 #ifdef HAVE_NETLOC
265     idx = network_attr.u.torus.node_index;
266 #endif
267 
268     return idx;
269 }
270