Get rid of ClusterCreationArgs in Torus/Dragonfly/Fat-tree.
NOTE: Routers aren't created anymore for Torus/Dragonfly/Fat-tree zones.
- This router was lost in the middle of topology connected through empty
routes (no links)
- In the past, the sg_platf created a router automatically for these
netzones since they shared the same sg_platf_new_cluster function.
- Impact on flatfier test: cluster_torus.xml.
void get_graph(const s_xbt_graph_t* graph, std::map<std::string, xbt_node_t, std::less<>>* nodes,
std::map<std::string, xbt_edge_t, std::less<>>* edges) override;
- virtual void create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, unsigned int position);
- virtual void parse_specific_arguments(ClusterCreationArgs*)
- {
- /* this routing method does not require any specific argument */
- }
+ void create_links_for_node(const ClusterCreationArgs* cluster, int id, int rank, unsigned int position);
unsigned int node_pos(int id) const { return id * num_links_per_node_; }
unsigned int node_pos_with_loopback(int id) const { return node_pos(id) + (has_loopback_ ? 1 : 0); }
explicit DragonflyZone(const std::string& name);
void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* into, double* latency) override;
- void parse_specific_arguments(ClusterCreationArgs* cluster) override;
+ /**
+ * @brief Parse topology parameters from string format
+ *
+ * @param topo_parameters Topology parameters, e.g. "3,4 ; 3,2 ; 3,1 ; 2"
+ */
+ static s4u::DragonflyParams parse_topo_parameters(const std::string& topo_parameters);
+
/** @brief Checks topology parameters */
static void check_topology(unsigned int n_groups, unsigned int groups_links, unsigned int n_chassis,
unsigned int chassis_links, unsigned int n_routers, unsigned int routers_links,
~FatTreeZone() override;
void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* into, double* latency) override;
- /** @brief Read the parameters in topo_parameters field. */
- void parse_specific_arguments(ClusterCreationArgs* cluster) override;
+ /**
+ * @brief Parse the topology parameters from string format
+ *
+ * @param topo_parameters String with topology, e.g. "2;4,4;1,2;1,2"
+ */
+ static s4u::FatTreeParams parse_topo_parameters(const std::string& topo_parameters);
/** @brief Checks topology parameters */
static void check_topology(unsigned int n_levels, const std::vector<unsigned int>& down_links,
const std::vector<unsigned int>& up_links, const std::vector<unsigned int>& link_count);
class XBT_PRIVATE TorusZone : public ClusterZone {
std::vector<unsigned int> dimensions_;
+ s4u::Link::SharingPolicy link_sharing_policy_; //!< torus links: sharing policy
+ double link_bw_; //!< torus links: bandwidth
+ double link_lat_; //!< torus links: latency
public:
using ClusterZone::ClusterZone;
- void create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, unsigned int position) override;
+ void create_links_for_node(int id, int rank, unsigned int position);
void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* into, double* latency) override;
- void parse_specific_arguments(ClusterCreationArgs* cluster) override;
void set_topology(const std::vector<unsigned int>& dimensions);
/** @brief Convert topology parameters from string to vector of uint */
static std::vector<unsigned int> parse_topo_parameters(const std::string& topo_parameters);
+ /** @brief Set the characteristics of links inside the Torus zone */
+ void set_link_characteristics(double bw, double lat, s4u::Link::SharingPolicy sharing_policy);
};
-/** @brief Create a regular torus zone with hosts as leafs */
-s4u::NetZone* create_torus_zone_with_hosts(const ClusterCreationArgs* cluster, const s4u::NetZone* parent);
-
} // namespace routing
} // namespace kernel
} // namespace simgrid
}
}
-void ClusterZone::create_links_for_node(ClusterCreationArgs* cluster, int id, int /*rank*/, unsigned int position)
+void ClusterZone::create_links_for_node(const ClusterCreationArgs* cluster, int id, int /*rank*/, unsigned int position)
{
std::string link_id = cluster->id + "_link_" + std::to_string(id);
num_nodes_per_blade_ = nodes;
}
-void DragonflyZone::parse_specific_arguments(ClusterCreationArgs* cluster)
+s4u::DragonflyParams DragonflyZone::parse_topo_parameters(const std::string& topo_parameters)
{
std::vector<std::string> parameters;
std::vector<std::string> tmp;
- boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
+ boost::split(parameters, topo_parameters, boost::is_any_of(";"));
if (parameters.size() != 4)
surf_parse_error(
if (tmp.size() != 2)
surf_parse_error("Dragonfly topologies are defined by 3 levels with 2 elements each, and one with one element");
+ unsigned int n_groups;
try {
- num_groups_ = std::stoi(tmp[0]);
+ n_groups = std::stoi(tmp[0]);
} catch (const std::invalid_argument&) {
throw std::invalid_argument(std::string("Invalid number of groups:") + tmp[0]);
}
+ unsigned int n_blue;
try {
- num_links_blue_ = std::stoi(tmp[1]);
+ n_blue = std::stoi(tmp[1]);
} catch (const std::invalid_argument&) {
throw std::invalid_argument(std::string("Invalid number of links for the blue level:") + tmp[1]);
}
if (tmp.size() != 2)
surf_parse_error("Dragonfly topologies are defined by 3 levels with 2 elements each, and one with one element");
+ unsigned int n_chassis;
try {
- num_chassis_per_group_ = std::stoi(tmp[0]);
+ n_chassis = std::stoi(tmp[0]);
} catch (const std::invalid_argument&) {
- throw std::invalid_argument(std::string("Invalid number of groups:") + tmp[0]);
+ throw std::invalid_argument(std::string("Invalid number of chassis:") + tmp[0]);
}
+ unsigned int n_black;
try {
- num_links_black_ = std::stoi(tmp[1]);
+ n_black = std::stoi(tmp[1]);
} catch (const std::invalid_argument&) {
throw std::invalid_argument(std::string("Invalid number of links for the black level:") + tmp[1]);
}
if (tmp.size() != 2)
surf_parse_error("Dragonfly topologies are defined by 3 levels with 2 elements each, and one with one element");
+ unsigned int n_routers;
try {
- num_blades_per_chassis_ = std::stoi(tmp[0]);
+ n_routers = std::stoi(tmp[0]);
} catch (const std::invalid_argument&) {
- throw std::invalid_argument(std::string("Invalid number of groups:") + tmp[0]);
+ throw std::invalid_argument(std::string("Invalid number of routers:") + tmp[0]);
}
+ unsigned int n_green;
try {
- num_links_green_ = std::stoi(tmp[1]);
+ n_green = std::stoi(tmp[1]);
} catch (const std::invalid_argument&) {
throw std::invalid_argument(std::string("Invalid number of links for the green level:") + tmp[1]);
}
// The last part of topo_parameters should be the number of nodes per blade
+ unsigned int n_nodes;
try {
- num_nodes_per_blade_ = std::stoi(parameters[3]);
+ n_nodes = std::stoi(parameters[3]);
} catch (const std::invalid_argument&) {
throw std::invalid_argument(std::string("Last parameter is not the amount of nodes per blade:") + parameters[3]);
}
-
- set_link_characteristics(cluster->bw, cluster->lat, cluster->sharing_policy);
+ return s4u::DragonflyParams({n_groups, n_blue}, {n_chassis, n_black}, {n_routers, n_green}, n_nodes);
}
/* Generate the cluster once every node is created */
num_port_lower_level_ = link_count;
}
-void FatTreeZone::parse_specific_arguments(ClusterCreationArgs* cluster)
+s4u::FatTreeParams FatTreeZone::parse_topo_parameters(const std::string& topo_parameters)
{
std::vector<std::string> parameters;
std::vector<std::string> tmp;
std::vector<unsigned int> down;
std::vector<unsigned int> up;
std::vector<unsigned int> count;
- boost::split(parameters, cluster->topo_parameters, boost::is_any_of(";"));
+ boost::split(parameters, topo_parameters, boost::is_any_of(";"));
surf_parse_assert(
parameters.size() == 4,
throw std::invalid_argument(std::string("Invalid lower level port number:") + port);
}
}
-
- /* set topology */
- FatTreeZone::check_topology(n_lev, down, up, count);
- set_topology(n_lev, down, up, count);
- /* saving internal links properties */
- set_link_characteristics(cluster->bw, cluster->lat, cluster->sharing_policy);
+ return s4u::FatTreeParams(n_lev, down, up, count);
}
void FatTreeZone::generate_dot_file(const std::string& filename) const
namespace kernel {
namespace routing {
-void TorusZone::create_links_for_node(ClusterCreationArgs* cluster, int id, int rank, unsigned int position)
+void TorusZone::create_links_for_node(int id, int rank, unsigned int position)
{
/* Create all links that exist in the torus. Each rank creates @a dimensions-1 links */
int dim_product = 1; // Needed to calculate the next neighbor_id
? rank - (current_dimension - 1) * dim_product
: rank + dim_product;
// name of neighbor is not right for non contiguous cluster radicals (as id != rank in this case)
- std::string link_id =
- std::string(cluster->id) + "_link_from_" + std::to_string(id) + "_to_" + std::to_string(neighbor_rank_id);
+ std::string link_id = get_name() + "_link_from_" + std::to_string(id) + "_to_" + std::to_string(neighbor_rank_id);
const s4u::Link* linkup;
const s4u::Link* linkdown;
- if (cluster->sharing_policy == s4u::Link::SharingPolicy::SPLITDUPLEX) {
- linkup = create_link(link_id + "_UP", std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
- linkdown = create_link(link_id + "_DOWN", std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
+ if (link_sharing_policy_ == s4u::Link::SharingPolicy::SPLITDUPLEX) {
+ linkup = create_link(link_id + "_UP", std::vector<double>{link_bw_})->set_latency(link_lat_)->seal();
+ linkdown = create_link(link_id + "_DOWN", std::vector<double>{link_bw_})->set_latency(link_lat_)->seal();
} else {
- linkup = create_link(link_id, std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
+ linkup = create_link(link_id, std::vector<double>{link_bw_})->set_latency(link_lat_)->seal();
linkdown = linkup;
}
/*
return dimensions;
}
-void TorusZone::parse_specific_arguments(ClusterCreationArgs* cluster)
+void TorusZone::set_link_characteristics(double bw, double lat, s4u::Link::SharingPolicy sharing_policy)
{
- set_topology(TorusZone::parse_topo_parameters(cluster->topo_parameters));
+ link_sharing_policy_ = sharing_policy;
+ link_bw_ = bw;
+ link_lat_ = lat;
}
void TorusZone::set_topology(const std::vector<unsigned int>& dimensions)
route->gw_dst = get_gateway(dst->id());
}
-/** @brief Auxiliary function to create hosts */
-static std::pair<kernel::routing::NetPoint*, kernel::routing::NetPoint*>
-create_torus_host(const kernel::routing::ClusterCreationArgs* cluster, s4u::NetZone* zone,
- const std::vector<unsigned int>& /*coord*/, int id)
-{
- std::string host_id = std::string(cluster->prefix) + std::to_string(id) + cluster->suffix;
- XBT_DEBUG("TorusCluster: creating host=%s speed=%f", host_id.c_str(), cluster->speeds.front());
- const s4u::Host* host = zone->create_host(host_id, cluster->speeds)
- ->set_core_count(cluster->core_amount)
- ->set_properties(cluster->properties)
- ->seal();
- return std::make_pair(host->get_netpoint(), nullptr);
-}
-
-/** @brief Auxiliary function to create loopback links */
-static s4u::Link* create_torus_loopback(const kernel::routing::ClusterCreationArgs* cluster, s4u::NetZone* zone,
- const std::vector<unsigned int>& /*coord*/, int id)
-{
- std::string link_id = std::string(cluster->id) + "_link_" + std::to_string(id) + "_loopback";
- XBT_DEBUG("TorusCluster: creating loopback link=%s bw=%f", link_id.c_str(), cluster->loopback_bw);
-
- s4u::Link* loopback = zone->create_link(link_id, cluster->loopback_bw)
- ->set_sharing_policy(simgrid::s4u::Link::SharingPolicy::FATPIPE)
- ->set_latency(cluster->loopback_lat)
- ->seal();
- return loopback;
-}
-
-/** @brief Auxiliary function to create limiter links */
-static s4u::Link* create_torus_limiter(const kernel::routing::ClusterCreationArgs* cluster, s4u::NetZone* zone,
- const std::vector<unsigned int>& /*coord*/, int id)
-{
- std::string link_id = std::string(cluster->id) + "_link_" + std::to_string(id) + "_limiter";
- XBT_DEBUG("TorusCluster: creating limiter link=%s bw=%f", link_id.c_str(), cluster->limiter_link);
-
- s4u::Link* limiter = zone->create_link(link_id, cluster->limiter_link)->seal();
- return limiter;
-}
-
-s4u::NetZone* create_torus_zone_with_hosts(const kernel::routing::ClusterCreationArgs* cluster,
- const s4u::NetZone* parent)
-{
- using namespace std::placeholders;
- auto set_host = std::bind(create_torus_host, cluster, _1, _2, _3);
- std::function<s4u::ClusterLinkCb> set_loopback{};
- std::function<s4u::ClusterLinkCb> set_limiter{};
-
- if (cluster->loopback_bw > 0 || cluster->loopback_lat > 0) {
- set_loopback = std::bind(create_torus_loopback, cluster, _1, _2, _3);
- }
-
- if (cluster->limiter_link > 0) {
- set_loopback = std::bind(create_torus_limiter, cluster, _1, _2, _3);
- }
-
- return s4u::create_torus_zone(cluster->id, parent, TorusZone::parse_topo_parameters(cluster->topo_parameters),
- cluster->bw, cluster->lat, cluster->sharing_policy, set_host, set_loopback,
- set_limiter);
-}
-
} // namespace routing
} // namespace kernel
if (parent)
zone->set_parent(parent->get_impl());
+ zone->set_link_characteristics(bandwidth, latency, sharing_policy);
+
for (int i = 0; i < tot_elements; i++) {
kernel::routing::NetPoint* netpoint;
Link* limiter;
Link* loopback;
zone->fill_leaf_from_cb(i, dimensions, set_netpoint, set_loopback, set_limiter, &netpoint, &loopback, &limiter);
- kernel::routing::ClusterCreationArgs params;
- params.id = name;
- params.bw = bandwidth;
- params.lat = latency;
- params.sharing_policy = sharing_policy;
- zone->create_links_for_node(¶ms, netpoint->id(), i, zone->node_pos_with_loopback_limiter(netpoint->id()));
+ zone->create_links_for_node(netpoint->id(), i, zone->node_pos_with_loopback_limiter(netpoint->id()));
}
return zone->get_iface();
current_host->add_disk(new_disk);
}
-void sg_platf_new_cluster(simgrid::kernel::routing::ClusterCreationArgs* cluster)
+/** @brief Auxiliary function to create hosts */
+static std::pair<simgrid::kernel::routing::NetPoint*, simgrid::kernel::routing::NetPoint*>
+sg_platf_cluster_create_host(const simgrid::kernel::routing::ClusterCreationArgs* cluster, simgrid::s4u::NetZone* zone,
+ const std::vector<unsigned int>& /*coord*/, int id)
{
- using simgrid::kernel::routing::ClusterZone;
+ std::string host_id = std::string(cluster->prefix) + std::to_string(id) + cluster->suffix;
+ XBT_DEBUG("Cluster: creating host=%s speed=%f", host_id.c_str(), cluster->speeds.front());
+ const simgrid::s4u::Host* host = zone->create_host(host_id, cluster->speeds)
+ ->set_core_count(cluster->core_amount)
+ ->set_properties(cluster->properties)
+ ->seal();
+ return std::make_pair(host->get_netpoint(), nullptr);
+}
+
+/** @brief Auxiliary function to create loopback links */
+static simgrid::s4u::Link*
+sg_platf_cluster_create_loopback(const simgrid::kernel::routing::ClusterCreationArgs* cluster,
+ simgrid::s4u::NetZone* zone, const std::vector<unsigned int>& /*coord*/, int id)
+{
+ std::string link_id = std::string(cluster->id) + "_link_" + std::to_string(id) + "_loopback";
+ XBT_DEBUG("Cluster: creating loopback link=%s bw=%f", link_id.c_str(), cluster->loopback_bw);
+
+ simgrid::s4u::Link* loopback = zone->create_link(link_id, cluster->loopback_bw)
+ ->set_sharing_policy(simgrid::s4u::Link::SharingPolicy::FATPIPE)
+ ->set_latency(cluster->loopback_lat)
+ ->seal();
+ return loopback;
+}
+
+/** @brief Auxiliary function to create limiter links */
+static simgrid::s4u::Link* sg_platf_cluster_create_limiter(const simgrid::kernel::routing::ClusterCreationArgs* cluster,
+ simgrid::s4u::NetZone* zone,
+ const std::vector<unsigned int>& /*coord*/, int id)
+{
+ std::string link_id = std::string(cluster->id) + "_link_" + std::to_string(id) + "_limiter";
+ XBT_DEBUG("Cluster: creating limiter link=%s bw=%f", link_id.c_str(), cluster->limiter_link);
+
+ simgrid::s4u::Link* limiter = zone->create_link(link_id, cluster->limiter_link)->seal();
+ return limiter;
+}
+
+/** @brief Create Torus, Fat-Tree and Dragonfly clusters */
+static void sg_platf_new_cluster_hierarchical(const simgrid::kernel::routing::ClusterCreationArgs* cluster)
+{
+ using namespace std::placeholders;
using simgrid::kernel::routing::DragonflyZone;
using simgrid::kernel::routing::FatTreeZone;
using simgrid::kernel::routing::TorusZone;
- int rankId = 0;
+ auto set_host = std::bind(sg_platf_cluster_create_host, cluster, _1, _2, _3);
+ std::function<simgrid::s4u::ClusterLinkCb> set_loopback{};
+ std::function<simgrid::s4u::ClusterLinkCb> set_limiter{};
- // What an inventive way of initializing the NetZone that I have as ancestor :-(
- simgrid::kernel::routing::ZoneCreationArgs zone;
- zone.id = cluster->id;
+ if (cluster->loopback_bw > 0 || cluster->loopback_lat > 0) {
+ set_loopback = std::bind(sg_platf_cluster_create_loopback, cluster, _1, _2, _3);
+ }
+
+ if (cluster->limiter_link > 0) {
+ set_loopback = std::bind(sg_platf_cluster_create_limiter, cluster, _1, _2, _3);
+ }
+
+ simgrid::s4u::NetZone* parent = routing_get_current() ? routing_get_current()->get_iface() : nullptr;
+ simgrid::s4u::NetZone* zone;
switch (cluster->topology) {
case simgrid::kernel::routing::ClusterTopology::TORUS:
- zone.routing = "ClusterTorus";
+ zone = simgrid::s4u::create_torus_zone(
+ cluster->id, parent, TorusZone::parse_topo_parameters(cluster->topo_parameters), cluster->bw, cluster->lat,
+ cluster->sharing_policy, set_host, set_loopback, set_limiter);
break;
case simgrid::kernel::routing::ClusterTopology::DRAGONFLY:
- zone.routing = "ClusterDragonfly";
+ zone = simgrid::s4u::create_dragonfly_zone(
+ cluster->id, parent, DragonflyZone::parse_topo_parameters(cluster->topo_parameters), cluster->bw,
+ cluster->lat, cluster->sharing_policy, set_host, set_loopback, set_limiter);
break;
case simgrid::kernel::routing::ClusterTopology::FAT_TREE:
- zone.routing = "ClusterFatTree";
+ zone = simgrid::s4u::create_fatTree_zone(
+ cluster->id, parent, FatTreeZone::parse_topo_parameters(cluster->topo_parameters), cluster->bw, cluster->lat,
+ cluster->sharing_policy, set_host, set_loopback, set_limiter);
break;
default:
- zone.routing = "Cluster";
+ THROW_IMPOSSIBLE;
break;
}
+ zone->seal();
+}
+
+/** @brief Create regular Cluster */
+static void sg_platf_new_cluster_flat(simgrid::kernel::routing::ClusterCreationArgs* cluster)
+{
+ using simgrid::kernel::routing::ClusterZone;
+
+ int rankId = 0;
+
+ // What an inventive way of initializing the NetZone that I have as ancestor :-(
+ simgrid::kernel::routing::ZoneCreationArgs zone;
+ zone.id = cluster->id;
+ zone.routing = "Cluster";
sg_platf_new_Zone_begin(&zone);
auto* current_zone = static_cast<ClusterZone*>(routing_get_current());
- current_zone->parse_specific_arguments(cluster);
for (auto const& elm : cluster->properties)
current_zone->get_iface()->set_property(elm.first, elm.second);
}
// call the cluster function that adds the others links
- if (cluster->topology == simgrid::kernel::routing::ClusterTopology::FAT_TREE) {
- static_cast<FatTreeZone*>(current_zone)->add_processing_node(i, limiter, loopback);
- } else {
- current_zone->create_links_for_node(cluster, i, rankId, current_zone->node_pos_with_loopback_limiter(rankId));
- }
+ current_zone->create_links_for_node(cluster, i, rankId, current_zone->node_pos_with_loopback_limiter(rankId));
rankId++;
}
XBT_DEBUG("</zone>");
sg_platf_new_Zone_seal();
+}
+
+void sg_platf_new_cluster(simgrid::kernel::routing::ClusterCreationArgs* cluster)
+{
+ switch (cluster->topology) {
+ case simgrid::kernel::routing::ClusterTopology::TORUS:
+ case simgrid::kernel::routing::ClusterTopology::DRAGONFLY:
+ case simgrid::kernel::routing::ClusterTopology::FAT_TREE:
+ sg_platf_new_cluster_hierarchical(cluster);
+ break;
+ default:
+ sg_platf_new_cluster_flat(cluster);
+ break;
+ }
simgrid::kernel::routing::on_cluster_creation(*cluster);
}
> <host id="node-7.simgrid.org" speed="1000000000"/>
> <host id="node-8.simgrid.org" speed="1000000000"/>
> <host id="node-9.simgrid.org" speed="1000000000"/>
-> <router id="node-bob_cluster_router.simgrid.org"/>
> <link id="__loopback__" bandwidth="10000000000" latency="0.000000000" sharing_policy="FATPIPE"/>
> <link id="bob_cluster_link_0_loopback" bandwidth="100000000" latency="0.000000000" sharing_policy="FATPIPE"/>
> <link id="bob_cluster_link_10_loopback" bandwidth="100000000" latency="0.000000000" sharing_policy="FATPIPE"/>
> <route src="node-0.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_0_to_3_UP"/><link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-0.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-1.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_0_to_1_DOWN"/>
> </route>
> <route src="node-1.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_0_to_1_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_3_UP"/><link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-1.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-10.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_9_to_10_DOWN"/><link_ctn id="bob_cluster_link_from_6_to_9_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-10.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_9_to_10_DOWN"/>
> </route>
-> <route src="node-10.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-11.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_11_to_9_UP"/><link_ctn id="bob_cluster_link_from_6_to_9_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-11.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_11_to_9_UP"/>
> </route>
-> <route src="node-11.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-2.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_2_to_0_UP"/>
> </route>
> <route src="node-2.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_2_to_0_UP"/><link_ctn id="bob_cluster_link_from_0_to_3_UP"/><link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-2.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-3.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_0_to_3_DOWN"/>
> </route>
> <route src="node-3.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-3.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-4.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_3_to_4_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_3_DOWN"/>
> </route>
> <route src="node-4.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_3_to_4_DOWN"/><link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-4.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-5.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_5_to_3_UP"/><link_ctn id="bob_cluster_link_from_0_to_3_DOWN"/>
> </route>
> <route src="node-5.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_5_to_3_UP"/><link_ctn id="bob_cluster_link_from_3_to_9_UP"/>
> </route>
-> <route src="node-5.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-6.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-6.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_6_to_9_UP"/>
> </route>
-> <route src="node-6.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-7.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_6_to_7_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-7.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_6_to_7_DOWN"/><link_ctn id="bob_cluster_link_from_6_to_9_UP"/>
> </route>
-> <route src="node-7.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-8.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_8_to_6_UP"/><link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-8.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_from_8_to_6_UP"/><link_ctn id="bob_cluster_link_from_6_to_9_UP"/>
> </route>
-> <route src="node-8.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
> <route src="node-9.simgrid.org" dst="node-0.simgrid.org">
> <link_ctn id="bob_cluster_link_from_6_to_9_DOWN"/><link_ctn id="bob_cluster_link_from_0_to_6_DOWN"/>
> </route>
> <route src="node-9.simgrid.org" dst="node-9.simgrid.org">
> <link_ctn id="bob_cluster_link_9_loopback"/>
> </route>
-> <route src="node-9.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-bob_cluster_router.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-0.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-1.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-10.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-11.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-2.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-3.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-4.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-5.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-6.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-7.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-8.simgrid.org">
->
-> </route>
-> <route src="node-bob_cluster_router.simgrid.org" dst="node-9.simgrid.org">
->
-> </route>
> </AS>
> </platform>