/* * Copyright (c) 2020 Intel, Inc. All rights reserved. * Copyright (c) 2021 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ * */ #include #include #include #include #include #include #define DEFAULT_NUM_SWITCHES 8 #define DEFAULT_NUM_FABPORTS 10 #define DEFAULT_NUM_EDGEPORTS 10 #define DEFAULT_NUM_NODES 8 #define DEFAULT_NUM_NICS 8 #define DEFAULT_NUM_GROUPS 2 static int iseven(int num) { return !(num & 1); } static int help = 0; typedef struct { int nswitches; int *members; } grptrk_t; int main(int argc, char **argv) { json_t *root, *switches, *fabricports, *edgeports; json_t *sw, *port, *cport, *links; json_t *nodes, *node, *nics; char *s; int idnum = 10; int jnum = 0; int pnum = 0; int n, nn; int nsw, nswitches = DEFAULT_NUM_SWITCHES; int numfabports = DEFAULT_NUM_FABPORTS; int numedgeports = DEFAULT_NUM_EDGEPORTS; int nnics = DEFAULT_NUM_NICS; int nnodes = DEFAULT_NUM_NODES; int ngrps = DEFAULT_NUM_GROUPS; char *tmp; int opt; grptrk_t map[100]; char *outfile = NULL; static struct option myoptions[] = {{"file", required_argument, NULL, 'f'}, {"nswitches", required_argument, NULL, 's'}, {"nfabports", required_argument, NULL, 'p'}, {"nedgeports", required_argument, NULL, 'e'}, {"nnodes", required_argument, NULL, 'c'}, {"nnics", required_argument, NULL, 'n'}, {"ngrps", required_argument, NULL, 'g'}, {"help", no_argument, &help, 1}}; int option_index; /* check for options */ while ((opt = getopt_long(argc, argv, "f:p:e:c:n", myoptions, &option_index)) != -1) { switch (opt) { case 'f': outfile = optarg; break; case 's': nswitches = strtol(optarg, NULL, 10); break; case 'p': numfabports = strtol(optarg, NULL, 10); break; case 'e': numedgeports = strtol(optarg, NULL, 10); break; case 'c': nnodes = strtol(optarg, NULL, 10); break; case 'n': nnics = strtol(optarg, NULL, 10); break; case 'g': ngrps = strtol(optarg, NULL, 10); break; default: fprintf(stderr, "Usage: %s\n Options:\n" " [-f] [output file - will add .json extension]\n" " [-s] [number of switches]\n" " [-g] [number of groups to organize the switches into (<100)\n" " [-p] [number of fabricports per switch]\n" " [-e] [number of edge ports per switch]\n" " [-c] [number of nodes]\n" " [-n] [number of NICs per node]\n", argv[0]); exit(1); } } if (help) { fprintf(stdout, "Usage: %s\n Options:\n" " [-f] [output file - will add .json extension]\n" " [-s] [number of switches]\n" " [-p] [number of fabricports per switch]\n" " [-e] [number of edge ports per switch]\n" " [-c] [number of nodes]\n" " [-n] [number of NICs per node]\n", argv[0]); exit(0); } /* create a JSON object */ root = json_object(); /* we will be defining an array of switches */ switches = json_array(); json_object_set_new(root, "switches", switches); for (n = 0; n < ngrps; n++) { map[n].nswitches = 0; map[n].members = (int *) malloc(nswitches * sizeof(int)); } for (nsw = 0; nsw < nswitches; nsw++) { /* each switch contains an object that starts with its identifiers */ sw = json_object(); (void) asprintf(&tmp, "0x30000c0r21b%d", nsw); json_object_set_new(sw, "IP", json_string(tmp)); free(tmp); nn = nsw % ngrps; json_object_set_new(sw, "grpID", json_integer(nn)); map[nn].members[map[nn].nswitches] = nsw; map[nn].nswitches++; json_object_set_new(sw, "swcNum", json_integer(nsw)); /* each switch contains an array of fabric ports */ fabricports = json_array(); for (n = 0; n < numfabports; n++) { port = json_object(); /* each fabric port has an ID */ (void) asprintf(&tmp, "0x30000c0r21a01%d", idnum); json_object_set_new(port, "id", json_string(tmp)); free(tmp); ++idnum; /* each fabric port has a "meta" object that contains the connection port */ cport = json_object(); (void) asprintf(&tmp, "0x30000c0r21j%dp%d", jnum, pnum); json_object_set_new(cport, "conn_port", json_string(tmp)); json_object_set_new(port, "meta", cport); free(tmp); if (iseven(n)) { pnum = 1; } else { pnum = 0; ++jnum; } /* add the port to the array of fabricports */ json_array_append(fabricports, port); } /* add the fabricports to the switch */ json_object_set_new(sw, "fabricports", fabricports); /* each switch also contains an array of edge ports */ edgeports = json_array(); for (n = 0; n < numedgeports; n++) { port = json_object(); /* each edge port has an ID */ (void) asprintf(&tmp, "0x30000c0r21a01%d", idnum); json_object_set_new(port, "id", json_string(tmp)); free(tmp); ++idnum; /* each edge port has a "meta" object that contains the connection port */ cport = json_object(); (void) asprintf(&tmp, "0x30000c0r21j%dp%d", jnum, pnum); json_object_set_new(cport, "conn_port", json_string(tmp)); json_object_set_new(port, "meta", cport); free(tmp); if (iseven(n)) { pnum = 1; } else { pnum = 0; ++jnum; } /* add the port to the array of edgeports */ json_array_append(edgeports, port); } /* add the edgeports to the switch */ json_object_set_new(sw, "edgeports", edgeports); /* add the switch to the array */ json_array_append(switches, sw); } /* add the nmber of groups */ json_object_set_new(root, "numGroups", json_integer(ngrps)); /* set the max number of switches in a group */ nsw = (nswitches / ngrps) + (nswitches % ngrps); json_object_set_new(root, "maxNumLocalSwitches", json_integer(nsw)); /* define an array of links */ links = json_array(); json_object_set_new(root, "links", links); /* put some arbitrary endpoint info in it */ for (n = 0; n < numfabports; n++) { port = json_object(); (void) asprintf(&tmp, "0x30000c0r21a01%d", idnum); json_object_set_new(port, "endpoint1", json_string(tmp)); free(tmp); ++idnum; (void) asprintf(&tmp, "0x30000c0r21a01%d", idnum); json_object_set_new(port, "endpoint2", json_string(tmp)); free(tmp); ++idnum; /* add the port to the array of links */ json_array_append(links, port); } /* define an array of nodes */ nodes = json_array(); json_object_set_new(root, "nodes", nodes); nsw = 0; for (nn = 0; nn < nnodes; nn++) { /* each node contains an object that starts with its name */ node = json_object(); (void) asprintf(&tmp, "node%03d", nn); json_object_set_new(node, "name", json_string(tmp)); free(tmp); /* each node contains a set of NICs */ nics = json_array(); for (n = 0; n < nnics; n++) { port = json_object(); /* each NIC has an ID */ (void) asprintf(&tmp, "0x30000c0r21a01%d", idnum); json_object_set_new(port, "id", json_string(tmp)); free(tmp); ++idnum; /* define a group for this node */ opt = nn % ngrps; /* and a connection - each NIC needs to point to a * switch in the same group */ nsw = n % map[opt].nswitches; json_object_set_new(port, "switch", json_integer(map[opt].members[nsw])); /* add the port to the NIC array */ json_array_append(nics, port); } /* add the NICs to the node */ json_object_set_new(node, "nics", nics); /* add the node to the array */ json_array_append(nodes, node); } if (NULL == outfile) { s = json_dumps(root, JSON_INDENT(4)); puts(s); } else { (void) asprintf(&tmp, "%s.json", outfile); json_dump_file(root, tmp, JSON_INDENT(4)); free(tmp); } json_decref(root); return 0; }