+ std::vector<char*> names;
+
+ if (link->policy == SURF_LINK_FULLDUPLEX) {
+ names.push_back(bprintf("%s_UP", link->id));
+ names.push_back(bprintf("%s_DOWN", link->id));
+ } else {
+ names.push_back(xbt_strdup(link->id));
+ }
+ for (auto link_name : names) {
+ Link *l = surf_network_model->createLink(link_name, link->bandwidth, link->latency, link->policy, link->properties);
+
+ if (link->latency_trace)
+ l->setLatencyTrace(link->latency_trace);
+ if (link->bandwidth_trace)
+ l->setBandwidthTrace(link->bandwidth_trace);
+ if (link->state_trace)
+ l->setStateTrace(link->state_trace);
+
+ xbt_free(link_name);
+ }
+
+ simgrid::surf::on_link(link);
+}
+
+void sg_platf_new_cluster(sg_platf_cluster_cbarg_t cluster)
+{
+ using simgrid::kernel::routing::AsCluster;
+ using simgrid::kernel::routing::AsClusterDragonfly;
+ using simgrid::kernel::routing::AsClusterFatTree;
+ using simgrid::kernel::routing::AsClusterTorus;
+
+ int rankId=0;
+
+ s_sg_platf_link_cbarg_t link;
+
+ // What an inventive way of initializing the AS that I have as ancestor :-(
+ s_sg_platf_AS_cbarg_t AS;
+ AS.id = cluster->id;
+ switch (cluster->topology) {
+ case SURF_CLUSTER_TORUS:
+ AS.routing = A_surfxml_AS_routing_ClusterTorus;
+ break;
+ case SURF_CLUSTER_DRAGONFLY:
+ AS.routing = A_surfxml_AS_routing_ClusterDragonfly;
+ break;
+ case SURF_CLUSTER_FAT_TREE:
+ AS.routing = A_surfxml_AS_routing_ClusterFatTree;
+ break;
+ default:
+ AS.routing = A_surfxml_AS_routing_Cluster;
+ break;
+ }
+ sg_platf_new_AS_begin(&AS);
+ simgrid::kernel::routing::AsCluster *current_as = static_cast<AsCluster*>(routing_get_current());
+ current_as->parse_specific_arguments(cluster);
+
+ if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){
+ current_as->linkCountPerNode_++;
+ current_as->hasLoopback_ = 1;
+ }
+
+ if(cluster->limiter_link!=0){
+ current_as->linkCountPerNode_++;
+ current_as->hasLimiter_ = 1;
+ }
+
+ std::vector<int> *radicals = explodesRadical(cluster->radical);
+ for (int i : *radicals) {
+ char * host_id = bprintf("%s%d%s", cluster->prefix, i, cluster->suffix);
+ char * link_id = bprintf("%s_link_%d", cluster->id, i);
+
+ XBT_DEBUG("<host\tid=\"%s\"\tpower=\"%f\">", host_id, cluster->speed);
+
+ s_sg_platf_host_cbarg_t host;
+ memset(&host, 0, sizeof(host));
+ host.id = host_id;
+ if ((cluster->properties != nullptr) && (!xbt_dict_is_empty(cluster->properties))) {
+ xbt_dict_cursor_t cursor=nullptr;
+ char *key,*data;
+ host.properties = xbt_dict_new();
+
+ xbt_dict_foreach(cluster->properties,cursor,key,data) {
+ xbt_dict_set(host.properties, key, xbt_strdup(data),free);
+ }
+ }
+
+ host.speed_per_pstate.push_back(cluster->speed);
+ host.pstate = 0;
+ host.core_amount = cluster->core_amount;
+ host.coord = "";
+ sg_platf_new_host(&host);
+ XBT_DEBUG("</host>");
+
+ XBT_DEBUG("<link\tid=\"%s\"\tbw=\"%f\"\tlat=\"%f\"/>", link_id, cluster->bw, cluster->lat);
+
+ s_surf_parsing_link_up_down_t info_lim;
+ s_surf_parsing_link_up_down_t info_loop;
+ // All links are saved in a matrix;
+ // every row describes a single node; every node may have multiple links.
+ // the first column may store a link from x to x if p_has_loopback is set
+ // the second column may store a limiter link if p_has_limiter is set
+ // other columns are to store one or more link for the node
+
+ //add a loopback link
+ if(cluster->loopback_bw!=0 || cluster->loopback_lat!=0){
+ char *tmp_link = bprintf("%s_loopback", link_id);
+ XBT_DEBUG("<loopback\tid=\"%s\"\tbw=\"%f\"/>", tmp_link, cluster->loopback_bw);
+
+ memset(&link, 0, sizeof(link));
+ link.id = tmp_link;
+ link.bandwidth = cluster->loopback_bw;
+ link.latency = cluster->loopback_lat;
+ link.policy = SURF_LINK_FATPIPE;
+ sg_platf_new_link(&link);
+ info_loop.linkUp = Link::byName(tmp_link);
+ info_loop.linkDown = Link::byName(tmp_link);
+ free(tmp_link);
+
+ auto as_cluster = static_cast<AsCluster*>(current_as);
+ if (rankId*as_cluster->linkCountPerNode_ >= as_cluster->privateLinks_.size())
+ as_cluster->privateLinks_.resize(rankId*as_cluster->linkCountPerNode_,{nullptr, nullptr});
+ as_cluster->privateLinks_.insert(as_cluster->privateLinks_.begin() + rankId*as_cluster->linkCountPerNode_,
+ info_loop);
+ }
+
+ //add a limiter link (shared link to account for maximal bandwidth of the node)
+ if(cluster->limiter_link!=0){
+ char *tmp_link = bprintf("%s_limiter", link_id);
+ XBT_DEBUG("<limiter\tid=\"%s\"\tbw=\"%f\"/>", tmp_link, cluster->limiter_link);
+
+ memset(&link, 0, sizeof(link));
+ link.id = tmp_link;
+ link.bandwidth = cluster->limiter_link;
+ link.latency = 0;
+ link.policy = SURF_LINK_SHARED;
+ sg_platf_new_link(&link);
+ info_lim.linkUp = info_lim.linkDown = Link::byName(tmp_link);
+ free(tmp_link);
+ current_as->privateLinks_.insert(current_as->privateLinks_.begin() + rankId * current_as->linkCountPerNode_ +
+ current_as->hasLoopback_ , info_lim);
+ }
+
+ //call the cluster function that adds the others links
+ if (cluster->topology == SURF_CLUSTER_FAT_TREE) {
+ ((AsClusterFatTree*) current_as)->addProcessingNode(i);
+ }
+ else {
+ current_as->create_links_for_node(cluster, i, rankId,
+ rankId*current_as->linkCountPerNode_ + current_as->hasLoopback_ + current_as->hasLimiter_ );
+ }
+ xbt_free(link_id);
+ xbt_free(host_id);
+ rankId++;