/* * Copyright © 2016-2018 Inria. All rights reserved. * * $COPYRIGHT$ * * Additional copyrights may follow * See COPYING in top-level directory. * * $HEADER$ */ #define _GNU_SOURCE // for asprintf #include #include #include #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include // for dirname #include #include #include #include #include #include #include int global_link_idx = 0; typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char dest[20]; /* key */ float total_gbits; UT_array *physical_link_idx; int *partitions; } edge_t; typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char physical_id[20]; /* key */ long logical_id; int type; char *description; edge_t *edges; int main_partition; char *hostname; int *partitions; UT_array *physical_links; } node_t; node_t *nodes = NULL; typedef struct { int int_id; // TODO long long int ports[2]; node_t *dest; char *width; char *speed; float gbits; char *description; int *partitions; int other_id; edge_t *parent_edge; node_t *parent_node; } physical_link_t; UT_icd physical_link_icd = {sizeof(physical_link_t), NULL, NULL, NULL }; UT_icd partitions_icd = {sizeof(char *), NULL, NULL, NULL }; UT_array *partitions = NULL; const int NODE_TYPE_HOST = 0; const int NODE_TYPE_SWITH = 1; const int NODE_TYPE_UNKNOWN = 2; /* Route tables */ typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char physical_id[20]; /* key */ int port; } route_dest_t; typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char physical_id[20]; /* key */ route_dest_t *dest; } route_source_t; route_source_t *routes = NULL; /* Paths tables */ typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char physical_id[20]; /* key */ node_t *node; UT_array *links; } path_dest_t; typedef struct { UT_hash_handle hh; /* makes this structure hashable */ char physical_id[20]; /* key */ node_t *node; path_dest_t *dest; } path_source_t; path_source_t *paths = NULL; int read_routes(char *subnet, char *path, char *route_filename); int read_discover(char *subnet, char *discover_path, char *filename); int write_into_file(char *subnet, char *path, char *hwlocpath); static void get_match(char *line, int nmatch, regmatch_t pmatch[], char *matches[]) { for (int i = 0; i < nmatch; i++) { regmatch_t current_match = pmatch[i]; size_t len = current_match.rm_eo-current_match.rm_so; matches[i] = (char *)malloc((len+1)*sizeof(char)); strncpy(matches[i], line+current_match.rm_so, len); matches[i][len] = '\0'; } } /* We suppose the description of nodes is like that: ([^ ]*).* * while \1 is the hostname */ static char *node_find_hostname(node_t *node) { char *name = node->description; int max_size = strlen(name); char *hostname = (char *)malloc(max_size*sizeof(char)); /* Looking for the name of the hostname */ int i = 0; if (name[0] == '\'') name++; while (i < max_size && ((name[i] >= 'a' && name[i] <= 'z') || (name[i] >= '0' && name[i] <= '9') || (name[i] == '-'))) { hostname[i] = name[i]; i++; } hostname[i++] = '\0'; char *old_hostname = hostname; hostname = realloc(hostname, i*sizeof(char)); if (!hostname) { fprintf(stderr, "Oups: cannot reallocate memory\n"); hostname = old_hostname; } return hostname; } node_t *get_node(node_t **nodes, char *type, char *lid, char *guid, char *subnet, char *desc) { node_t *node; char *id; asprintf(&id, "%.4s:%.4s:%.4s:%.4s", guid, guid+4, guid+8, guid+12); // TODO check guid format HASH_FIND_STR(*nodes, id, node); /* id already in the hash? */ if (!node) { size_t size = sizeof(*node)+sizeof(char)*(strlen(desc)+1); node = (node_t *) malloc(size); sprintf(node->physical_id, "%s", id); node->logical_id = atol(lid); if (!strcmp(type, "CA")) node->type = NODE_TYPE_HOST; else if (!strcmp(type, "SW")) node->type = NODE_TYPE_SWITH; else node->type = NODE_TYPE_UNKNOWN; node->edges = NULL; node->description = strdup(desc); node->hostname = node_find_hostname(node); node->main_partition = -1; node->partitions = NULL; utarray_new(node->physical_links, &physical_link_icd); HASH_ADD_STR(*nodes, physical_id, node); /* guid: name of key field */ } free(id); return node; } static int find_other_physical_link(physical_link_t *link) { node_t *dest = link->dest; unsigned int dest_port = link->ports[1]; physical_link_t *other_link = (physical_link_t *) utarray_eltptr(dest->physical_links, dest_port-1); return other_link->int_id; } static float compute_gbits(char *speed, char *width) { float rate; float encoding; float gb_per_x; int x; if (strcmp(speed, "SDR")) { rate = 2.5; encoding = 8.0/10; } else if (strcmp(speed, "DDR")) { rate = 5; encoding = 8.0/10; } else if (strcmp(speed, "QDR")) { rate = 10; encoding = 8.0/10; } else if (strcmp(speed, "FDR")) { rate = 14.0625; encoding = 64.0/66; } else if (strcmp(speed, "FDR10")) { rate = 10; encoding = 64.0/66; } else if (strcmp(speed, "EDR")) { rate = 25; encoding = 64.0/66; } else { return 1; } gb_per_x = rate*encoding; regex_t width_re; regcomp(&width_re, "([[:digit:]]*)x", REG_EXTENDED); if (!regexec(&width_re, width, (size_t)0, NULL, 0)) { x = atoi(width); } else { x = 0.0; } regfree(&width_re); return x*gb_per_x; } int build_paths(void) { node_t *node_src, *node_dest, *node_tmp1, *node_tmp2; HASH_ITER(hh, nodes, node_src, node_tmp1) { if (node_src->type != NODE_TYPE_HOST) continue; char *id_src = node_src->physical_id; path_source_t *path = (path_source_t *) malloc(sizeof(path_source_t)); sprintf(path->physical_id, "%s", id_src); path->node = node_src; path->dest = NULL; HASH_ADD_STR(paths, physical_id, path); HASH_ITER(hh, nodes, node_dest, node_tmp2) { if (node_dest->type != NODE_TYPE_HOST) continue; if (node_dest == node_src) { continue; } UT_array *found_links = NULL; utarray_new(found_links, &ut_ptr_icd); int completed = 1; char *id_dest = node_dest->physical_id; physical_link_t *link = (physical_link_t *) utarray_eltptr(node_src->physical_links, 0); utarray_push_back(found_links, &link); node_t *node_cur = link->dest; while (node_cur != node_dest) { route_source_t *route_source; route_dest_t *route_dest; char *id_cur = node_cur->physical_id; HASH_FIND_STR(routes, id_cur, route_source); if (!route_source) { completed = 0; break; } HASH_FIND_STR(route_source->dest, id_dest, route_dest); if (!route_dest) { completed = 0; break; } unsigned int port = route_dest->port; link = (physical_link_t *) utarray_eltptr(node_cur->physical_links, port-1); utarray_push_back(found_links, &link); node_cur = link->dest; } if (completed) { path_dest_t *path_dest = (path_dest_t *) malloc(sizeof(path_dest_t)); sprintf(path_dest->physical_id, "%s", id_dest); path_dest->node = node_dest; path_dest->links = found_links; HASH_ADD_STR(path->dest, physical_id, path_dest); } else { utarray_free(found_links); } } } return 0; } /* We suppose the hostname of nodes is like that: ([a-z]*).* * while \1 is the name of the partition */ static char *node_find_partition_name(node_t *node) { char *name; int max_size; char *partition; max_size = strlen(node->hostname); partition = (char *)malloc((max_size+1)*sizeof(char)); name = node->hostname; /* Looking for the name of the partition */ int i = 0; while (i < max_size && (name[i] >= 'a' && name[i] <= 'z')) { partition[i] = name[i]; i++; } partition[i++] = '\0'; char *old_partition = partition; partition = realloc(partition, i*sizeof(char)); if (!partition) { fprintf(stderr, "Oups: cannot reallocate memory\n"); partition = old_partition; } return partition; } int netloc_topology_find_partitions(void) { int ret = 0; int num_nodes; char **partition_names; node_t **hosts; num_nodes = HASH_COUNT(nodes); partition_names = (char **)malloc(num_nodes*sizeof(char *)); hosts = (node_t **)malloc(num_nodes*sizeof(node_t *)); /* Save all the partition names */ int n = 0; node_t *node, *node_tmp; HASH_ITER(hh, nodes, node, node_tmp) { if (node->type != NODE_TYPE_HOST) continue; partition_names[n] = node_find_partition_name(node); hosts[n] = node; n++; } /* Associate the field partition in the nodes to the correct partition * index */ int num_hosts = n; int num_partitions = 0; for (int n1 = 0; n1 < num_hosts; n1++) { if (!partition_names[n1]) continue; partition_names[num_partitions] = partition_names[n1]; hosts[n1]->main_partition = num_partitions; for (int n2 = n1+1; n2 < num_hosts; n2++) { if (!partition_names[n2]) continue; if (!strcmp(partition_names[n1], partition_names[n2])) { free(partition_names[n2]); partition_names[n2] = NULL; hosts[n2]->main_partition = num_partitions; } } num_partitions++; } printf("%d partitions found\n", num_partitions); utarray_new(partitions, &partitions_icd); utarray_reserve(partitions, num_partitions); for (int p = 0; p < num_partitions; p++) { printf("\t'%s'\n", partition_names[p]); utarray_push_back(partitions, partition_names+p); } free(partition_names); free(hosts); return ret; } int netloc_topology_set_partitions(void) { /* Find the main partition for each node */ netloc_topology_find_partitions(); node_t *node, *node_tmp; HASH_ITER(hh, nodes, node, node_tmp) { node->partitions = (int *) calloc(utarray_len(partitions), sizeof(int)); if (node->main_partition != -1) node->partitions[node->main_partition] = 1; edge_t *edge, *edge_tmp; HASH_ITER(hh, node->edges, edge, edge_tmp) { edge->partitions = (int *) calloc(utarray_len(partitions), sizeof(int)); } } /* Set the partitions for the physical links considering if there is in a * path between two nodes of a partition */ path_source_t *path_src, *path_src_tmp; HASH_ITER(hh, paths, path_src, path_src_tmp) { node_t *node_src = path_src->node; int partition = node_src->main_partition; path_dest_t *path_dest, *path_dest_tmp; HASH_ITER(hh, path_src->dest, path_dest, path_dest_tmp) { node_t *node_dest = path_dest->node; if (node_dest->main_partition != partition) continue; for (unsigned int l = 0; l < utarray_len(path_dest->links); l++) { physical_link_t *link = *(physical_link_t **) utarray_eltptr(path_dest->links, l); if (!link->partitions) { link->partitions = (int *) calloc(utarray_len(partitions), sizeof(int)); } link->partitions[partition] = 1; link->parent_node->partitions[partition] = 1; link->parent_edge->partitions[partition] = 1; } } } return 0; } void help(char *name, FILE *f) { fprintf(f, "Usage: %s " "[--hwloc-dir ]\n" "\thwloc-dir can be an absolute path " "or a relative path from out-dir\n", name); } int main(int argc, char **argv) { DIR *indir, *outdir; char *prog_name = basename(argv[0]); char *inpath = NULL, *outpath = NULL, *hwlocpath = NULL; if (argc != 2 && argc != 3 && argc != 5) { goto error_param; } argc--; argv++; if (!strcmp(*argv, "--help")) { help(prog_name, stdout); return 0; } inpath = *argv; argc--; argv++; if (!argc) goto error_param; outpath = *argv; argc--; argv++; while (argc > 0) { if (!strcmp(*argv, "--hwloc-dir")) { argc--; argv++; if (!argc) goto error_param; hwlocpath = *argv; } else if (!strcmp(*argv, "--help")) { help(prog_name, stdout); return 0; } else { goto error_param; } argc--; argv++; } if (!outpath || !inpath) { goto error_param; } indir = opendir(inpath); if (!indir) { fprintf(stderr, "Couldn't open input directory: \"%s\"\n", inpath); perror("opendir"); return 2; } outdir = opendir(outpath); if (!outdir) { fprintf(stderr, "Couldn't open output directory: \"%s\"\n", outpath); perror("opendir"); closedir(outdir); return 2; } if (hwlocpath) { char *realpath; if (hwlocpath[0] != '/') { asprintf(&realpath, "%s/%s", outpath, hwlocpath); } else { realpath = strdup(hwlocpath); } DIR *hwlocdir = opendir(realpath); if (!hwlocdir) { fprintf(stderr, "Couldn't open hwloc directory: \"%s\"\n", realpath); perror("opendir"); closedir(indir); closedir(outdir); free(realpath); return 2; } free(realpath); closedir(hwlocdir); } regex_t subnet_regexp; regcomp(&subnet_regexp, "^ib-subnet-([0-9a-fA-F:]{19}).txt$", REG_EXTENDED); struct dirent *entry; while ((entry = readdir(indir))) { nodes = NULL; int subnet_found; char *filename = entry->d_name; subnet_found = !(regexec(&subnet_regexp, filename, 0, NULL, 0)); if (subnet_found) { global_link_idx = 0; char *discover_filename; char *route_filename; char *subnet; asprintf(&subnet, "%.19s", filename+10); discover_filename = filename; read_discover(subnet, inpath, discover_filename); asprintf(&route_filename, "%s/ibroutes-%s", inpath, subnet); struct stat s; int err = stat(route_filename, &s); if (-1 == err) { if (errno == ENOENT) { printf("No route directory found for subnet %s\n", subnet); } else { perror("stat"); exit(1); } } else { if (S_ISDIR(s.st_mode)) { char *route_filename; asprintf(&route_filename, "ibroutes-%s", subnet); read_routes(subnet, inpath, route_filename); free(route_filename); } else { printf("No route directory found for subnet %s\n", subnet); } } free(route_filename); build_paths(); netloc_topology_set_partitions(); write_into_file(subnet, outpath, hwlocpath); /* Free node hash table */ node_t *node, *node_tmp; HASH_ITER(hh, nodes, node, node_tmp) { HASH_DEL(nodes, node); /* Free nodes */ free(node->description); /* Edges */ edge_t *edge, *edge_tmp; HASH_ITER(hh, node->edges, edge, edge_tmp) { HASH_DEL(node->edges, edge); utarray_free(edge->physical_link_idx); free(edge->partitions); free(edge); } free(node->hostname); free(node->partitions); /* Physical links */ for (unsigned int l = 0; l < utarray_len(node->physical_links); l++) { physical_link_t *link = (physical_link_t *) utarray_eltptr(node->physical_links, l); free(link->width); free(link->speed); free(link->description); free(link->partitions); } utarray_free(node->physical_links); free(node); } /* Free Partitions */ for (char **ppartition = (char **)utarray_front(partitions); ppartition != NULL; ppartition = (char **)utarray_next(partitions, ppartition)) { free(*ppartition); } utarray_free(partitions); /* Free Routes */ route_source_t *route, *route_tmp; HASH_ITER(hh, routes, route, route_tmp) { HASH_DEL(routes, route); route_dest_t *routed, *routed_tmp; HASH_ITER(hh, route->dest, routed, routed_tmp) { HASH_DEL(route->dest, routed); free(routed); } free(route); } /* Free Paths */ path_source_t *path, *path_tmp; HASH_ITER(hh, paths, path, path_tmp) { HASH_DEL(paths, path); path_dest_t *pathd, *pathd_tmp; HASH_ITER(hh, path->dest, pathd, pathd_tmp) { HASH_DEL(path->dest, pathd); utarray_free(pathd->links); free(pathd); } free(path); } free(subnet); } } regfree(&subnet_regexp); closedir(indir); closedir(outdir); return 0; error_param: fprintf(stderr, "Wrong parameters\n"); help(prog_name, stderr); return 1; } int read_discover(char *subnet, char *path, char *filename) { char *line = NULL; size_t size = 0; char *discover_path; FILE *discover_file; asprintf(&discover_path, "%s/%s", path, filename); discover_file = fopen(discover_path, "r"); free(discover_path); if (!discover_file) { perror("fopen"); exit(-1); } regex_t dr_re; regcomp(&dr_re, "^DR", REG_EXTENDED); regex_t link_re; regcomp(&link_re, "^" "(CA|SW)[[:space:]]+" // Source type "([[:digit:]]+)[[:space:]]+" // Source lid "([[:digit:]]+)[[:space:]]+" // Source port id "0x([0-9a-f]{16})[[:space:]]+" // Source guid "([[:digit:]]+x)[[:space:]]" // Connection width "([^[:space:]]*)[[:space:]]+" // Connection speed "-[[:space:]]+" // Dash seperator "(CA|SW)[[:space:]]+" // Dest type "([[:digit:]]+)[[:space:]]+" // Dest lid "([[:digit:]]+)[[:space:]]+" // Dest port id "0x([0-9a-f]{16})[[:space:]]+" // Dest guid "\\([[:space:]]*(.*)[[:space:]]*\\)" // Description , REG_EXTENDED); regex_t nolink_re; regcomp(&nolink_re, "^" "(CA|SW)[[:space:]]+" // Source type "([[:digit:]]+)[[:space:]]+" // Source lid "([[:digit:]]+)[[:space:]]+" // Source port id "0x([0-9a-f]{16})[[:space:]]+" // Source guid , REG_EXTENDED); int read; errno = 0; /* getline can return -1 even if no error (EOF) */ while ((read = getline(&line, &size, discover_file)) > 0) { const int link_nfields = 12; const int nolink_nfields = 7; const int max_nfields = 12; regmatch_t pmatch[max_nfields]; char *matches[max_nfields]; char *src_type; char *src_lid; char *src_port_id; char *src_guid; char *width; char *speed; char *dest_type; char *dest_lid; char *dest_port_id; char *dest_guid; char *link_desc; char *src_desc = NULL; char *dest_desc = NULL; int have_peer; if (!regexec(&dr_re, line, (size_t)0, NULL, 0)) { /* DR line */ continue; } else if (!regexec(&link_re, line, (size_t)link_nfields, pmatch, 0)) { /* peer associated: port is active */ have_peer = 1; get_match(line, link_nfields, pmatch, matches); src_type = matches[ 1]; src_lid = matches[ 2]; src_port_id = matches[ 3]; src_guid = matches[ 4]; width = matches[ 5]; speed = matches[ 6]; dest_type = matches[ 7]; dest_lid = matches[ 8]; dest_port_id = matches[ 9]; dest_guid = matches[10]; link_desc = matches[11]; free(matches[0]); /* Analyse description */ regex_t desc_re; regcomp(&desc_re, "(.*)" " - " "(.*)", REG_EXTENDED); if (!regexec(&desc_re, link_desc, (size_t)3, pmatch, 0)) { get_match(link_desc, 3, pmatch, matches); src_desc = matches[1]; dest_desc = matches[2]; free(matches[0]); } else { src_desc = (char *)calloc(1, sizeof(char)); dest_desc = (char *)calloc(1, sizeof(char)); } regfree(&desc_re); } else if (!regexec(&nolink_re, line, (size_t)nolink_nfields, pmatch, 0)) { /* no peer associated: port is not active */ have_peer = 0; get_match(line, nolink_nfields, pmatch, matches); src_type = matches[ 1]; src_lid = matches[ 2]; src_port_id = matches[ 3]; src_guid = matches[ 4]; width = matches[ 5]; speed = matches[ 6]; free(matches[0]); } else { printf("Warning: line not recognized: \n\t%s\n", line); continue; } /* Compute gbits */ float gbits = compute_gbits(speed, width); /* Add the link to the edge list */ if (have_peer) { /* Get the source node */ node_t *src_node = get_node(&nodes, src_type, src_lid, src_guid, subnet, src_desc); node_t *dest_node = get_node(&nodes, dest_type, dest_lid, dest_guid, subnet, dest_desc); edge_t *edge; HASH_FIND_STR(src_node->edges, dest_node->physical_id, edge); /* Creation of the edge */ if (!edge) { edge = (edge_t *) malloc(sizeof(edge_t)); strcpy(edge->dest, dest_node->physical_id); edge->total_gbits = 0; edge->partitions = NULL; utarray_new(edge->physical_link_idx, &ut_int_icd); HASH_ADD_STR(src_node->edges, dest, edge); } /* Creation of the physical link */ physical_link_t link[1]; link->int_id = global_link_idx++; link->ports[0] = atoi(src_port_id); link->ports[1] = atoi(dest_port_id); link->width = strdup(width); link->speed = strdup(speed); link->dest = dest_node; link->gbits = gbits; edge->total_gbits += gbits; link->description = strdup(link_desc); link->partitions = NULL; link->parent_edge = edge; link->parent_node = src_node; link->other_id = -1; unsigned int port_idx = link->ports[0]-1; /* NB: there is no function to set a specific index */ if (port_idx+1 > utarray_len(src_node->physical_links)) { utarray_insert(src_node->physical_links, link, port_idx); } else { physical_link_t *dest_link = (physical_link_t *) utarray_eltptr(src_node->physical_links, port_idx); memcpy(dest_link, link, sizeof(physical_link_t)); } utarray_push_back(edge->physical_link_idx, &port_idx); free(src_desc); free(dest_desc); free(dest_type); free(dest_lid); free(dest_port_id); free(dest_guid); free(link_desc); } free(src_type); free(src_lid); free(src_port_id); free(src_guid); free(width); free(speed); } int failed = 0; if (read == -1 && errno) { perror("getline:"); failed = 1; } free(line); regfree(&dr_re); regfree(&link_re); regfree(&nolink_re); fclose(discover_file); if (failed) exit(-1); /* Find the link in the other way */ node_t *node, *node_tmp; HASH_ITER(hh, nodes, node, node_tmp) { unsigned int num_links = utarray_len(node->physical_links); for (unsigned int i = 0; i < num_links; i++) { physical_link_t *link = (physical_link_t *) utarray_eltptr(node->physical_links, i); if (!link->dest) continue; link->other_id = find_other_physical_link(link); } } return 0; } char *partition_list_to_string(int *partition_list) { if (!partition_list) return strdup(""); int first = 1; int offset = 0; int num_partitions = utarray_len(partitions); char tmp[20]; int max_length = num_partitions*(sprintf(tmp, "%d", num_partitions)+1)+1; char *string = (char *)malloc(max_length*sizeof(char)); string[0] = '\0'; for (int p = 0; p < num_partitions; p++) { if (partition_list[p] != 0) { if (!first) offset += sprintf(string+offset, ":"); offset += sprintf(string+offset, "%d", p); first = 0; } } return string; } int write_into_file(char *subnet, char *path, char *hwlocpath) { char *output_path; asprintf(&output_path, "%s/IB-%s-nodes.txt", path, subnet); FILE *output = fopen(output_path, "w"); if (!output) { perror("fopen"); printf("Wrong output_path: %s\n", output_path); exit(-1); } free(output_path); fprintf(output, "%d\n", NETLOCFILE_VERSION); fprintf(output, "%s\n", subnet); fprintf(output, "%s\n", hwlocpath? hwlocpath: ""); /* Write nodes into file */ fprintf(output, "%d\n", HASH_COUNT(nodes)); node_t *node, *node_tmp; HASH_ITER(hh, nodes, node, node_tmp) { fprintf(output, "%s,", node->physical_id); fprintf(output, "%ld,", node->logical_id); fprintf(output, "%d,", node->type); char *partition_str = partition_list_to_string(node->partitions); fprintf(output, "%s,", partition_str); free(partition_str); fprintf(output, "%s,", node->description); fprintf(output, "%s", node->hostname); fprintf(output, "\n"); } /* Write edges into file */ HASH_ITER(hh, nodes, node, node_tmp) { edge_t *edge, *edge_tmp; fprintf(output, "%s", node->physical_id); HASH_ITER(hh, node->edges, edge, edge_tmp) { unsigned int num_links = utarray_len(edge->physical_link_idx); fprintf(output, ",%s,", edge->dest); fprintf(output, "%f,", edge->total_gbits); char *partition_str = partition_list_to_string(edge->partitions); fprintf(output, "%s,", partition_str); free(partition_str); fprintf(output, "%u,", num_links); for (unsigned int l = 0; l < num_links; l++) { unsigned int link_idx = *(unsigned int *) utarray_eltptr(edge->physical_link_idx, l); physical_link_t *link = (physical_link_t *) utarray_eltptr(node->physical_links, link_idx); fprintf(output, "%d,", link->int_id); fprintf(output, "%d,", link->ports[0]); fprintf(output, "%d,", link->ports[1]); fprintf(output, "%s,", link->width); fprintf(output, "%s,", link->speed); fprintf(output, "%f,", link->gbits); fprintf(output, "%s,", link->description); fprintf(output, "%d,", link->other_id); char *partition_str = partition_list_to_string(link->partitions); fprintf(output, "%s", partition_str); free(partition_str); fprintf(output, "%s", l == num_links-1 ? "": ","); } } fprintf(output, "\n"); } /* Write partitions into file */ for (char **ppartition = (char **)utarray_front(partitions); ppartition != NULL; ppartition = (char **)utarray_next(partitions, ppartition)) fprintf(output, "%s%s", *ppartition, utarray_next(partitions, ppartition)? ",": ""); fprintf(output, "\n"); /* Write paths into file */ path_source_t *path_src, *path_src_tmp; HASH_ITER(hh, paths, path_src, path_src_tmp) { node_t *node_src = path_src->node; path_dest_t *path_dest, *path_dest_tmp; HASH_ITER(hh, path_src->dest, path_dest, path_dest_tmp) { node_t *node_dest = path_dest->node; fprintf(output, "%s,%s", node_src->physical_id, node_dest->physical_id); for (unsigned int l = 0; l < utarray_len(path_dest->links); l++) { physical_link_t *link = *(physical_link_t **) utarray_eltptr(path_dest->links, l); fprintf(output, ",%d", link->int_id); } fprintf(output, "\n"); } } fclose(output); return 0; } int read_routes(char *subnet, char *path, char *route_dirname) { char *route_path; DIR *dir; asprintf(&route_path, "%s/%s", path, route_dirname); dir = opendir(route_path); printf("Read subnet: %s\n", subnet); if (dir != NULL) { char *line = NULL; size_t size = 0; regex_t route_filename_regexp; regcomp(&route_filename_regexp, "^ibroute-[0-9a-fA-F:]{19}-([0-9]*).txt$", REG_EXTENDED); struct dirent *entry; while ((entry = readdir(dir))) { char *filename = entry->d_name; if (!(regexec(&route_filename_regexp, filename, 0, NULL, 0))) { char *route_filename; asprintf(&route_filename, "%s/%s", route_path, filename); FILE *route_file = fopen(route_filename, "r"); if (!route_file) { perror("fopen"); exit(-1); } free(route_filename); regex_t header_re; regcomp(&header_re, "^Unicast lids.*" "guid[[:space:]]+0x([0-9a-f]{16}).*:", REG_EXTENDED); regex_t route_re; regcomp(&route_re, "^" "0x([0-9a-f]+)[[:space:]]+" // Dest lid "([[:digit:]]+)[[:space:]]+" // Port id ":[[:space:]]+[(]" // Separator "(Channel Adapter|Switch)[[:space:]]+" // Type "portguid 0x([0-9a-f]{16}):" // Dest guid , REG_EXTENDED); int read; route_source_t *route = NULL; while ((read = getline(&line, &size, route_file)) > 0) { regmatch_t pmatch[5]; char *matches[5]; int port; char dest_guid[20]; if (!regexec(&header_re, line, (size_t)2, pmatch, 0)) { char guid[20]; get_match(line, 2, pmatch, matches); sprintf(guid, "%.4s:%.4s:%.4s:%.4s", matches[1], matches[1]+4, matches[1]+8, matches[1]+12); for (int m = 0; m < 2; m++) { free(matches[m]); } HASH_FIND_STR(routes, guid, route); if (!route) { route = (route_source_t *) malloc(sizeof(route_source_t)); sprintf(route->physical_id, "%s", guid); route->dest = NULL; HASH_ADD_STR(routes, physical_id, route); } } else if (!regexec(&route_re, line, (size_t)5, pmatch, 0)) { if (!route) { fprintf(stderr, "Malformed route file %s\n", filename); exit(-1); } route_dest_t *route_dest; get_match(line, 5, pmatch, matches); port = atoi(matches[2]); sprintf(dest_guid, "%.4s:%.4s:%.4s:%.4s", matches[4], matches[4]+4, matches[4]+8, matches[4]+12); for (int m = 0; m < 5; m++) { free(matches[m]); } route_dest = (route_dest_t *) malloc(sizeof(route_dest_t)); sprintf(route_dest->physical_id, "%s", dest_guid); route_dest->port = port; HASH_ADD_STR(route->dest, physical_id, route_dest); } } fclose(route_file); regfree(&header_re); regfree(&route_re); } } free(line); regfree(&route_filename_regexp); } free(route_path); closedir(dir); return 0; }