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