1 /*
2 * Copyright © 2014 Cisco Systems, Inc. All rights reserved.
3 * Copyright © 2013-2014 University of Wisconsin-La Crosse.
4 * All rights reserved.
5 * Copyright © 2015-2017 Inria. All rights reserved.
6 *
7 * $COPYRIGHT$
8 *
9 * Additional copyrights may follow
10 * See COPYING in top-level directory.
11 *
12 * $HEADER$
13 */
14
15 #ifndef _NETLOC_PRIVATE_H_
16 #define _NETLOC_PRIVATE_H_
17
18 #include <hwloc.h>
19 #include <netloc.h>
20 #include <netloc/uthash.h>
21 #include <netloc/utarray.h>
22 #include <private/autogen/config.h>
23
24 #define NETLOCFILE_VERSION 1
25
26 #ifdef NETLOC_SCOTCH
27 #include <stdint.h>
28 #include <scotch.h>
29 #define NETLOC_int SCOTCH_Num
30 #else
31 #define NETLOC_int int
32 #endif
33
34 /*
35 * "Import" a few things from hwloc
36 */
37 #define __netloc_attribute_unused __hwloc_attribute_unused
38 #define __netloc_attribute_malloc __hwloc_attribute_malloc
39 #define __netloc_attribute_const __hwloc_attribute_const
40 #define __netloc_attribute_pure __hwloc_attribute_pure
41 #define __netloc_attribute_deprecated __hwloc_attribute_deprecated
42 #define __netloc_attribute_may_alias __hwloc_attribute_may_alias
43 #define NETLOC_DECLSPEC HWLOC_DECLSPEC
44
45
46 /**********************************************************************
47 * Types
48 **********************************************************************/
49
50 /**
51 * Definitions for Comparators
52 * \sa These are the return values from the following functions:
53 * netloc_network_compare, netloc_dt_edge_t_compare, netloc_dt_node_t_compare
54 */
55 typedef enum {
56 NETLOC_CMP_SAME = 0, /**< Compared as the Same */
57 NETLOC_CMP_SIMILAR = -1, /**< Compared as Similar, but not the Same */
58 NETLOC_CMP_DIFF = -2 /**< Compared as Different */
59 } netloc_compare_type_t;
60
61 /**
62 * Enumerated type for the various types of supported networks
63 */
64 typedef enum {
65 NETLOC_NETWORK_TYPE_ETHERNET = 1, /**< Ethernet network */
66 NETLOC_NETWORK_TYPE_INFINIBAND = 2, /**< InfiniBand network */
67 NETLOC_NETWORK_TYPE_INVALID = 3 /**< Invalid network */
68 } netloc_network_type_t;
69
70 /**
71 * Enumerated type for the various types of supported topologies
72 */
73 typedef enum {
74 NETLOC_TOPOLOGY_TYPE_INVALID = -1, /**< Invalid */
75 NETLOC_TOPOLOGY_TYPE_TREE = 1, /**< Tree */
76 } netloc_topology_type_t;
77
78 /**
79 * Enumerated type for the various types of nodes
80 */
81 typedef enum {
82 NETLOC_NODE_TYPE_HOST = 0, /**< Host (a.k.a., network addressable endpoint - e.g., MAC Address) node */
83 NETLOC_NODE_TYPE_SWITCH = 1, /**< Switch node */
84 NETLOC_NODE_TYPE_INVALID = 2 /**< Invalid node */
85 } netloc_node_type_t;
86
87 typedef enum {
88 NETLOC_ARCH_TREE = 0, /* Fat tree */
89 } netloc_arch_type_t;
90
91
92 /* Pre declarations to avoid inter dependency problems */
93 /** \cond IGNORE */
94 struct netloc_topology_t;
95 typedef struct netloc_topology_t netloc_topology_t;
96 struct netloc_node_t;
97 typedef struct netloc_node_t netloc_node_t;
98 struct netloc_edge_t;
99 typedef struct netloc_edge_t netloc_edge_t;
100 struct netloc_physical_link_t;
101 typedef struct netloc_physical_link_t netloc_physical_link_t;
102 struct netloc_path_t;
103 typedef struct netloc_path_t netloc_path_t;
104
105 struct netloc_arch_tree_t;
106 typedef struct netloc_arch_tree_t netloc_arch_tree_t;
107 struct netloc_arch_node_t;
108 typedef struct netloc_arch_node_t netloc_arch_node_t;
109 struct netloc_arch_node_slot_t;
110 typedef struct netloc_arch_node_slot_t netloc_arch_node_slot_t;
111 struct netloc_arch_t;
112 typedef struct netloc_arch_t netloc_arch_t;
113 /** \endcond */
114
115 /**
116 * \struct netloc_topology_t
117 * \brief Netloc Topology Context
118 *
119 * An opaque data structure used to reference a network topology.
120 *
121 * \note Must be initialized with \ref netloc_topology_construct()
122 */
123 struct netloc_topology_t {
124 /** Topology path */
125 char *topopath;
126 /** Subnet ID */
127 char *subnet_id;
128
129 /** Node List */
130 netloc_node_t *nodes; /* Hash table of nodes by physical_id */
131 netloc_node_t *nodesByHostname; /* Hash table of nodes by hostname */
132
133 netloc_physical_link_t *physical_links; /* Hash table with physcial links */
134
135 /** Partition List */
136 UT_array *partitions;
137
138 /** Hwloc topology List */
139 char *hwlocpath;
140 UT_array *topos;
141 hwloc_topology_t *hwloc_topos;
142
143 /** Type of the graph */
144 netloc_topology_type_t type;
145 };
146
147 /**
148 * \brief Netloc Node Type
149 *
150 * Represents the concept of a node (a.k.a., vertex, endpoint) within a network
151 * graph. This could be a server or a network switch. The \ref node_type parameter
152 * will distinguish the exact type of node this represents in the graph.
153 */
154 struct netloc_node_t {
155 UT_hash_handle hh; /* makes this structure hashable with physical_id */
156 UT_hash_handle hh2; /* makes this structure hashable with hostname */
157
158 /** Physical ID of the node */
159 char physical_id[20];
160
161 /** Logical ID of the node (if any) */
162 int logical_id;
163
164 /** Type of the node */
165 netloc_node_type_t type;
166
167 /* Pointer to physical_links */
168 UT_array *physical_links;
169
170 /** Description information from discovery (if any) */
171 char *description;
172
173 /**
174 * Application-given private data pointer.
175 * Initialized to NULL, and not used by the netloc library.
176 */
177 void * userdata;
178
179 /** Outgoing edges from this node */
180 netloc_edge_t *edges;
181
182 UT_array *subnodes; /* the group of nodes for the virtual nodes */
183
184 netloc_path_t *paths;
185
186 char *hostname;
187
188 UT_array *partitions; /* index in the list from the topology */
189
190 hwloc_topology_t hwlocTopo;
191 int hwlocTopoIdx;
192 };
193
194 /**
195 * \brief Netloc Edge Type
196 *
197 * Represents the concept of a directed edge within a network graph.
198 *
199 * \note We do not point to the netloc_node_t structure directly to
200 * simplify the representation, and allow the information to more easily
201 * be entered into the data store without circular references.
202 * \todo JJH Is the note above still true?
203 */
204 struct netloc_edge_t {
205 UT_hash_handle hh; /* makes this structure hashable */
206
207 netloc_node_t *dest;
208
209 int id;
210
211 /** Pointers to the parent node */
212 netloc_node_t *node;
213
214 /* Pointer to physical_links */
215 UT_array *physical_links;
216
217 /** total gbits of the links */
218 float total_gbits;
219
220 UT_array *partitions; /* index in the list from the topology */
221
222 UT_array *subnode_edges; /* for edges going to virtual nodes */
223
224 struct netloc_edge_t *other_way;
225
226 /**
227 * Application-given private data pointer.
228 * Initialized to NULL, and not used by the netloc library.
229 */
230 void * userdata;
231 };
232
233
234 struct netloc_physical_link_t {
235 UT_hash_handle hh; /* makes this structure hashable */
236
237 int id; // TODO long long
238 netloc_node_t *src;
239 netloc_node_t *dest;
240 int ports[2];
241 char *width;
242 char *speed;
243
244 netloc_edge_t *edge;
245
246 int other_way_id;
247 struct netloc_physical_link_t *other_way;
248
249 UT_array *partitions; /* index in the list from the topology */
250
251 /** gbits of the link from speed and width */
252 float gbits;
253
254 /** Description information from discovery (if any) */
255 char *description;
256 };
257
258 struct netloc_path_t {
259 UT_hash_handle hh; /* makes this structure hashable */
260 char dest_id[20];
261 UT_array *links;
262 };
263
264
265 /**********************************************************************
266 * Architecture structures
267 **********************************************************************/
268 struct netloc_arch_tree_t {
269 NETLOC_int num_levels;
270 NETLOC_int *degrees;
271 NETLOC_int *cost;
272 };
273
274 struct netloc_arch_node_t {
275 UT_hash_handle hh; /* makes this structure hashable */
276 char *name; /* Hash key */
277 netloc_node_t *node; /* Corresponding node */
278 int idx_in_topo; /* idx with ghost hosts to have complete topo */
279 int num_slots; /* it is not the real number of slots but the maximum slot idx */
280 int *slot_idx; /* corresponding idx in slot_tree */
281 int *slot_os_idx; /* corresponding os index for each leaf in tree */
282 netloc_arch_tree_t *slot_tree; /* Tree built from hwloc */
283 int num_current_slots; /* Number of PUs */
284 NETLOC_int *current_slots; /* indices in the complete tree */
285 int *slot_ranks; /* corresponding MPI rank for each leaf in tree */
286 };
287
288 struct netloc_arch_node_slot_t {
289 netloc_arch_node_t *node;
290 int slot;
291 };
292
293 struct netloc_arch_t {
294 netloc_topology_t *topology;
295 int has_slots; /* if slots are included in the architecture */
296 netloc_arch_type_t type;
297 union {
298 netloc_arch_tree_t *node_tree;
299 netloc_arch_tree_t *global_tree;
300 } arch;
301 netloc_arch_node_t *nodes_by_name;
302 netloc_arch_node_slot_t *node_slot_by_idx; /* node_slot by index in complete topo */
303 NETLOC_int num_current_hosts; /* if has_slots, host is a slot, else host is a node */
304 NETLOC_int *current_hosts; /* indices in the complete topology */
305 };
306
307 /**********************************************************************
308 * Topology Functions
309 **********************************************************************/
310 /**
311 * Allocate a topology handle.
312 *
313 * User is responsible for calling \ref netloc_detach on the topology handle.
314 * The network parameter information is deep copied into the topology handle, so the
315 * user may destruct the network handle after calling this function and/or reuse
316 * the network handle.
317 *
318 * \returns NETLOC_SUCCESS on success
319 * \returns NETLOC_ERROR upon an error.
320 */
321 netloc_topology_t *netloc_topology_construct(char *path);
322
323 /**
324 * Destruct a topology handle
325 *
326 * \param topology A valid pointer to a \ref netloc_topology_t handle created
327 * from a prior call to \ref netloc_topology_construct.
328 *
329 * \returns NETLOC_SUCCESS on success
330 * \returns NETLOC_ERROR upon an error.
331 */
332 int netloc_topology_destruct(netloc_topology_t *topology);
333
334 int netloc_topology_find_partition_idx(netloc_topology_t *topology, char *partition_name);
335
336 int netloc_topology_read_hwloc(netloc_topology_t *topology, int num_nodes,
337 netloc_node_t **node_list);
338
339 #define netloc_topology_iter_partitions(topology,partition) \
340 for ((partition) = (char **)utarray_front(topology->partitions); \
341 (partition) != NULL; \
342 (partition) = (char **)utarray_next(topology->partitions, partition))
343
344 #define netloc_topology_iter_hwloctopos(topology,hwloctopo) \
345 for ((hwloctopo) = (char **)utarray_front(topology->topos); \
346 (hwloctopo) != NULL; \
347 (hwloctopo) = (char **)utarray_next(topology->topos, hwloctopo))
348
349 #define netloc_topology_find_node(topology,node_id,node) \
350 HASH_FIND_STR(topology->nodes, node_id, node)
351
352 #define netloc_topology_iter_nodes(topology,node,_tmp) \
353 HASH_ITER(hh, topology->nodes, node, _tmp)
354
355 #define netloc_topology_num_nodes(topology) \
356 HASH_COUNT(topology->nodes)
357
358 /*************************************************/
359
360
361 /**
362 * Constructor for netloc_node_t
363 *
364 * User is responsible for calling the destructor on the handle.
365 *
366 * Returns
367 * A newly allocated pointer to the network information.
368 */
369 netloc_node_t *netloc_node_construct(void);
370
371 /**
372 * Destructor for netloc_node_t
373 *
374 * \param node A valid node handle
375 *
376 * Returns
377 * NETLOC_SUCCESS on success
378 * NETLOC_ERROR on error
379 */
380 int netloc_node_destruct(netloc_node_t *node);
381
382 char *netloc_node_pretty_print(netloc_node_t* node);
383
384 #define netloc_node_get_num_subnodes(node) \
385 utarray_len((node)->subnodes)
386
387 #define netloc_node_get_subnode(node,i) \
388 (*(netloc_node_t **)utarray_eltptr((node)->subnodes, (i)))
389
390 #define netloc_node_get_num_edges(node) \
391 utarray_len((node)->edges)
392
393 #define netloc_node_get_edge(node,i) \
394 (*(netloc_edge_t **)utarray_eltptr((node)->edges, (i)))
395
396 #define netloc_node_iter_edges(node,edge,_tmp) \
397 HASH_ITER(hh, node->edges, edge, _tmp)
398
399 #define netloc_node_iter_paths(node,path,_tmp) \
400 HASH_ITER(hh, node->paths, path, _tmp)
401
402 #define netloc_node_is_host(node) \
403 (node->type == NETLOC_NODE_TYPE_HOST)
404
405 #define netloc_node_is_switch(node) \
406 (node->type == NETLOC_NODE_TYPE_SWITCH)
407
408 #define netloc_node_iter_paths(node, path,_tmp) \
409 HASH_ITER(hh, node->paths, path, _tmp)
410
411 int netloc_node_is_in_partition(netloc_node_t *node, int partition);
412
413 /*************************************************/
414
415
416 /**
417 * Constructor for netloc_edge_t
418 *
419 * User is responsible for calling the destructor on the handle.
420 *
421 * Returns
422 * A newly allocated pointer to the edge information.
423 */
424 netloc_edge_t *netloc_edge_construct(void);
425
426 /**
427 * Destructor for netloc_edge_t
428 *
429 * \param edge A valid edge handle
430 *
431 * Returns
432 * NETLOC_SUCCESS on success
433 * NETLOC_ERROR on error
434 */
435 int netloc_edge_destruct(netloc_edge_t *edge);
436
437 char * netloc_edge_pretty_print(netloc_edge_t* edge);
438
439 void netloc_edge_reset_uid(void);
440
441 int netloc_edge_is_in_partition(netloc_edge_t *edge, int partition);
442
443 #define netloc_edge_get_num_links(edge) \
444 utarray_len((edge)->physical_links)
445
446 #define netloc_edge_get_link(edge,i) \
447 (*(netloc_physical_link_t **)utarray_eltptr((edge)->physical_links, (i)))
448
449 #define netloc_edge_get_num_subedges(edge) \
450 utarray_len((edge)->subnode_edges)
451
452 #define netloc_edge_get_subedge(edge,i) \
453 (*(netloc_edge_t **)utarray_eltptr((edge)->subnode_edges, (i)))
454
455 /*************************************************/
456
457
458 /**
459 * Constructor for netloc_physical_link_t
460 *
461 * User is responsible for calling the destructor on the handle.
462 *
463 * Returns
464 * A newly allocated pointer to the physical link information.
465 */
466 netloc_physical_link_t * netloc_physical_link_construct(void);
467
468 /**
469 * Destructor for netloc_physical_link_t
470 *
471 * Returns
472 * NETLOC_SUCCESS on success
473 * NETLOC_ERROR on error
474 */
475 int netloc_physical_link_destruct(netloc_physical_link_t *link);
476
477 char * netloc_link_pretty_print(netloc_physical_link_t* link);
478
479 /*************************************************/
480
481
482 netloc_path_t *netloc_path_construct(void);
483 int netloc_path_destruct(netloc_path_t *path);
484
485
486 /**********************************************************************
487 * Architecture functions
488 **********************************************************************/
489
490 netloc_arch_t * netloc_arch_construct(void);
491
492 int netloc_arch_destruct(netloc_arch_t *arch);
493
494 int netloc_arch_build(netloc_arch_t *arch, int add_slots);
495
496 int netloc_arch_set_current_resources(netloc_arch_t *arch);
497
498 int netloc_arch_set_global_resources(netloc_arch_t *arch);
499
500 int netloc_arch_node_get_hwloc_info(netloc_arch_node_t *arch);
501
502 void netloc_arch_tree_complete(netloc_arch_tree_t *tree, UT_array **down_degrees_by_level,
503 int num_hosts, int **parch_idx);
504
505 NETLOC_int netloc_arch_tree_num_leaves(netloc_arch_tree_t *tree);
506
507
508 /**********************************************************************
509 * Access functions of various elements of the topology
510 **********************************************************************/
511
512 #define netloc_get_num_partitions(object) \
513 utarray_len((object)->partitions)
514
515 #define netloc_get_partition(object,i) \
516 (*(int *)utarray_eltptr((object)->partitions, (i)))
517
518
519 #define netloc_path_iter_links(path,link) \
520 for ((link) = (netloc_physical_link_t **)utarray_front(path->links); \
521 (link) != NULL; \
522 (link) = (netloc_physical_link_t **)utarray_next(path->links, link))
523
524 /**********************************************************************
525 * Misc functions
526 **********************************************************************/
527
528 /**
529 * Decode the network type
530 *
531 * \param net_type A valid member of the \ref netloc_network_type_t type
532 *
533 * \returns NULL if the type is invalid
534 * \returns A string for that \ref netloc_network_type_t type
535 */
netloc_network_type_decode(netloc_network_type_t net_type)536 static inline const char * netloc_network_type_decode(netloc_network_type_t net_type) {
537 if( NETLOC_NETWORK_TYPE_ETHERNET == net_type ) {
538 return "ETH";
539 }
540 else if( NETLOC_NETWORK_TYPE_INFINIBAND == net_type ) {
541 return "IB";
542 }
543 else {
544 return NULL;
545 }
546 }
547
548 /**
549 * Decode the node type
550 *
551 * \param node_type A valid member of the \ref netloc_node_type_t type
552 *
553 * \returns NULL if the type is invalid
554 * \returns A string for that \ref netloc_node_type_t type
555 */
netloc_node_type_decode(netloc_node_type_t node_type)556 static inline const char * netloc_node_type_decode(netloc_node_type_t node_type) {
557 if( NETLOC_NODE_TYPE_SWITCH == node_type ) {
558 return "SW";
559 }
560 else if( NETLOC_NODE_TYPE_HOST == node_type ) {
561 return "CA";
562 }
563 else {
564 return NULL;
565 }
566 }
567
568 ssize_t netloc_line_get(char **lineptr, size_t *n, FILE *stream);
569
570 char *netloc_line_get_next_token(char **string, char c);
571
572 int netloc_build_comm_mat(char *filename, int *pn, double ***pmat);
573
574 #define STRDUP_IF_NOT_NULL(str) (NULL == str ? NULL : strdup(str))
575 #define STR_EMPTY_IF_NULL(str) (NULL == str ? "" : str)
576
577
578 #endif // _NETLOC_PRIVATE_H_
579