Allow creating hosts and adding CPUs during platform description.
With the C++ interface, it's easy to mix the creation of hosts and
routes in the same for loop. However, the old code had the assumption
that all hosts were created when we added new routes. This info was used
to initialize the routing_table.
Change code to resize the routing table when necessary (number of
elements in the zone has changed).
Zones with the error: Full and Floyd
Added UTs for this case.
include src/kernel/resource/profile/StochasticDatedValue.hpp
include src/kernel/routing/ClusterZone.cpp
include src/kernel/routing/DijkstraZone.cpp
+include src/kernel/routing/DijkstraZone_test.cpp
include src/kernel/routing/DragonflyZone.cpp
include src/kernel/routing/DragonflyZone_test.cpp
include src/kernel/routing/EmptyZone.cpp
include src/kernel/routing/FatTreeZone.cpp
include src/kernel/routing/FatTreeZone_test.cpp
include src/kernel/routing/FloydZone.cpp
+include src/kernel/routing/FloydZone_test.cpp
include src/kernel/routing/FullZone.cpp
+include src/kernel/routing/FullZone_test.cpp
include src/kernel/routing/NetPoint.cpp
include src/kernel/routing/NetZoneImpl.cpp
include src/kernel/routing/RoutedZone.cpp
sg4::Link* link_up = host_zone->create_link("link-up-" + cpu_name, link_bw)->set_latency(link_lat)->seal();
sg4::Link* link_down = host_zone->create_link("link-down-" + cpu_name, link_bw)->set_latency(link_lat)->seal();
/* link UP, connection from CPU to outer world */
- host_zone->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, {link_up}, false);
+ host_zone->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector<sg4::Link*>{link_up}, false);
/* link DOWN, connection from outer to CPU */
- host_zone->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, {link_down}, false);
+ host_zone->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{link_down}, false);
}
return std::make_pair(host_zone->get_netpoint(), gateway->get_netpoint());
}
*/
class XBT_PRIVATE FloydZone : public RoutedZone {
/* vars to compute the Floyd algorithm. */
- std::vector<int> predecessor_table_;
- std::vector<double> cost_table_;
- std::vector<Route*> link_table_;
+ std::vector<std::vector<int>> predecessor_table_;
+ std::vector<std::vector<double>> cost_table_;
+ std::vector<std::vector<std::unique_ptr<Route>>> link_table_;
void init_tables(unsigned int table_size);
void do_seal() override;
using RoutedZone::RoutedZone;
FloydZone(const FloydZone&) = delete;
FloydZone& operator=(const FloydZone&) = delete;
- ~FloydZone() override;
void get_local_route(NetPoint* src, NetPoint* dst, Route* into, double* latency) override;
void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
* computational requirements, but also the highest memory requirements (both in platform file and in memory).
*/
class XBT_PRIVATE FullZone : public RoutedZone {
- std::vector<Route*> routing_table_;
+ std::vector<std::vector<std::unique_ptr<Route>>> routing_table_;
void do_seal() override;
+ /** @brief Check and resize (if necessary) the routing table */
+ void check_routing_table();
public:
using RoutedZone::RoutedZone;
FullZone(const FullZone&) = delete;
FullZone& operator=(const FullZone) = delete;
- ~FullZone() override;
void get_local_route(NetPoint* src, NetPoint* dst, Route* into, double* latency) override;
void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
--- /dev/null
+/* Copyright (c) 2017-2021. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "catch.hpp"
+
+#include "simgrid/kernel/routing/DijkstraZone.hpp"
+#include "simgrid/kernel/routing/NetPoint.hpp"
+#include "simgrid/s4u/Engine.hpp"
+#include "simgrid/s4u/Host.hpp"
+#include "simgrid/s4u/NetZone.hpp"
+#include "src/surf/network_interface.hpp" //LinkImpl
+
+namespace {
+class EngineWrapper {
+ int argc = 1;
+ char* argv;
+ simgrid::s4u::Engine e;
+
+public:
+ explicit EngineWrapper(std::string name) : argv(&name[0]), e(&argc, &argv) {}
+};
+} // namespace
+
+TEST_CASE("kernel::routing::DijkstraZone: Creating Zone", "")
+{
+ EngineWrapper e("test");
+
+ REQUIRE(simgrid::s4u::create_dijkstra_zone("test", false));
+ REQUIRE(simgrid::s4u::create_dijkstra_zone("test2", true));
+}
+
+TEST_CASE("kernel::routing::DijkstraZone: mix new routes and hosts", "")
+{
+ EngineWrapper e("test");
+ auto* zone = simgrid::s4u::create_dijkstra_zone("test", false);
+
+ const simgrid::s4u::Host* nic = zone->create_host("nic", 1e9)->seal();
+ simgrid::s4u::Link* link = zone->create_link("my_link", 1e6)->seal();
+ for (int i = 0; i < 10; i++) {
+ std::string cpu_name = "CPU" + std::to_string(i);
+ const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
+ REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
+ std::vector<simgrid::s4u::Link*>{link}, true));
+ }
+}
\ No newline at end of file
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_floyd, surf, "Routing part of surf");
-#define TO_FLOYD_COST(i, j) (cost_table_)[(i) + (j)*table_size]
-#define TO_FLOYD_PRED(i, j) (predecessor_table_)[(i) + (j)*table_size]
-#define TO_FLOYD_LINK(i, j) (link_table_)[(i) + (j)*table_size]
-
namespace simgrid {
namespace kernel {
namespace routing {
-FloydZone::~FloydZone()
-{
- /* Delete link_table */
- for (auto const* link : link_table_)
- delete link;
-}
-
void FloydZone::init_tables(unsigned int table_size)
{
- if (link_table_.empty()) {
- /* Create and initialize Cost, Predecessor and Link tables */
- cost_table_.resize(table_size * table_size, DBL_MAX); /* link cost from host to host */
- predecessor_table_.resize(table_size * table_size, -1); /* predecessor host numbers */
- link_table_.resize(table_size * table_size, nullptr); /* actual link between src and dst */
+ if (link_table_.size() != table_size) {
+ /* Resize and initialize Cost, Predecessor and Link tables */
+ cost_table_.resize(table_size);
+ link_table_.resize(table_size);
+ predecessor_table_.resize(table_size);
+ for (auto& cost : cost_table_)
+ cost.resize(table_size, DBL_MAX); /* link cost from host to host */
+ for (auto& link : link_table_)
+ link.resize(table_size); /* actual link between src and dst */
+ for (auto& predecessor : predecessor_table_)
+ predecessor.resize(table_size, -1); /* predecessor host numbers */
}
}
void FloydZone::get_local_route(NetPoint* src, NetPoint* dst, Route* route, double* lat)
{
- unsigned int table_size = get_table_size();
-
get_route_check_params(src, dst);
/* create a result route */
std::vector<Route*> route_stack;
unsigned int cur = dst->id();
do {
- int pred = TO_FLOYD_PRED(src->id(), cur);
+ int pred = predecessor_table_[src->id()][cur];
if (pred == -1)
throw std::invalid_argument(xbt::string_printf("No route from '%s' to '%s'", src->get_cname(), dst->get_cname()));
- route_stack.push_back(TO_FLOYD_LINK(pred, cur));
+ route_stack.push_back(link_table_[pred][cur].get());
cur = pred;
} while (cur != src->id());
/* Check that the route does not already exist */
if (gw_dst && gw_src) // netzone route (to adapt the error message, if any)
- xbt_assert(nullptr == TO_FLOYD_LINK(src->id(), dst->id()),
+ xbt_assert(nullptr == link_table_[src->id()][dst->id()],
"The route between %s@%s and %s@%s already exists (Rq: routes are symmetrical by default).",
src->get_cname(), gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname());
else
- xbt_assert(nullptr == TO_FLOYD_LINK(src->id(), dst->id()),
+ xbt_assert(nullptr == link_table_[src->id()][dst->id()],
"The route between %s and %s already exists (Rq: routes are symmetrical by default).", src->get_cname(),
dst->get_cname());
- TO_FLOYD_LINK(src->id(), dst->id()) = new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, true);
- TO_FLOYD_PRED(src->id(), dst->id()) = src->id();
- TO_FLOYD_COST(src->id(), dst->id()) = (TO_FLOYD_LINK(src->id(), dst->id()))->link_list_.size();
+ link_table_[src->id()][dst->id()] =
+ std::unique_ptr<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, true));
+ predecessor_table_[src->id()][dst->id()] = src->id();
+ cost_table_[src->id()][dst->id()] = link_table_[src->id()][dst->id()]->link_list_.size();
if (symmetrical) {
if (gw_dst && gw_src) // netzone route (to adapt the error message, if any)
xbt_assert(
- nullptr == TO_FLOYD_LINK(dst->id(), src->id()),
+ nullptr == link_table_[dst->id()][src->id()],
"The route between %s@%s and %s@%s already exists. You should not declare the reverse path as symmetrical.",
dst->get_cname(), gw_dst->get_cname(), src->get_cname(), gw_src->get_cname());
else
- xbt_assert(nullptr == TO_FLOYD_LINK(dst->id(), src->id()),
+ xbt_assert(nullptr == link_table_[dst->id()][src->id()],
"The route between %s and %s already exists. You should not declare the reverse path as symmetrical.",
dst->get_cname(), src->get_cname());
XBT_DEBUG("Load NetzoneRoute from \"%s(%s)\" to \"%s(%s)\"", dst->get_cname(), gw_src->get_cname(),
src->get_cname(), gw_dst->get_cname());
- TO_FLOYD_LINK(dst->id(), src->id()) = new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, false);
- TO_FLOYD_PRED(dst->id(), src->id()) = dst->id();
- TO_FLOYD_COST(dst->id(), src->id()) =
- (TO_FLOYD_LINK(dst->id(), src->id()))->link_list_.size(); /* count of links, old model assume 1 */
+ link_table_[dst->id()][src->id()] =
+ std::unique_ptr<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, false));
+ predecessor_table_[dst->id()][src->id()] = dst->id();
+ cost_table_[dst->id()][src->id()] =
+ link_table_[dst->id()][src->id()]->link_list_.size(); /* count of links, old model assume 1 */
}
}
/* Add the loopback if needed */
if (get_network_model()->loopback_ && get_hierarchy() == RoutingMode::base) {
for (unsigned int i = 0; i < table_size; i++) {
- Route* route = TO_FLOYD_LINK(i, i);
+ auto& route = link_table_[i][i];
if (not route) {
- route = new Route();
+ route.reset(new Route());
route->link_list_.push_back(get_network_model()->loopback_);
- TO_FLOYD_LINK(i, i) = route;
- TO_FLOYD_PRED(i, i) = i;
- TO_FLOYD_COST(i, i) = 1;
+ predecessor_table_[i][i] = i;
+ cost_table_[i][i] = 1;
}
}
}
for (unsigned int c = 0; c < table_size; c++) {
for (unsigned int a = 0; a < table_size; a++) {
for (unsigned int b = 0; b < table_size; b++) {
- if (TO_FLOYD_COST(a, c) < DBL_MAX && TO_FLOYD_COST(c, b) < DBL_MAX &&
- (fabs(TO_FLOYD_COST(a, b) - DBL_MAX) < std::numeric_limits<double>::epsilon() ||
- (TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b) < TO_FLOYD_COST(a, b)))) {
- TO_FLOYD_COST(a, b) = TO_FLOYD_COST(a, c) + TO_FLOYD_COST(c, b);
- TO_FLOYD_PRED(a, b) = TO_FLOYD_PRED(c, b);
+ if (cost_table_[a][c] < DBL_MAX && cost_table_[c][b] < DBL_MAX &&
+ (fabs(cost_table_[a][b] - DBL_MAX) < std::numeric_limits<double>::epsilon() ||
+ (cost_table_[a][c] + cost_table_[c][b] < cost_table_[a][b]))) {
+ cost_table_[a][b] = cost_table_[a][c] + cost_table_[c][b];
+ predecessor_table_[a][b] = predecessor_table_[c][b];
}
}
}
--- /dev/null
+/* Copyright (c) 2017-2021. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "catch.hpp"
+
+#include "simgrid/kernel/routing/FloydZone.hpp"
+#include "simgrid/kernel/routing/NetPoint.hpp"
+#include "simgrid/s4u/Engine.hpp"
+#include "simgrid/s4u/Host.hpp"
+#include "simgrid/s4u/NetZone.hpp"
+#include "src/surf/network_interface.hpp" //LinkImpl
+
+namespace {
+class EngineWrapper {
+ int argc = 1;
+ char* argv;
+ simgrid::s4u::Engine e;
+
+public:
+ explicit EngineWrapper(std::string name) : argv(&name[0]), e(&argc, &argv) {}
+};
+} // namespace
+
+TEST_CASE("kernel::routing::FloydZone: Creating Zone", "")
+{
+ EngineWrapper e("test");
+
+ REQUIRE(simgrid::s4u::create_floyd_zone("test"));
+}
+
+TEST_CASE("kernel::routing::FloydZone: mix new routes and hosts", "")
+{
+ EngineWrapper e("test");
+ auto* zone = simgrid::s4u::create_floyd_zone("test");
+
+ const simgrid::s4u::Host* nic = zone->create_host("nic", 1e9)->seal();
+ simgrid::s4u::Link* link = zone->create_link("my_link", 1e6)->seal();
+ for (int i = 0; i < 10; i++) {
+ std::string cpu_name = "CPU" + std::to_string(i);
+ const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
+ REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
+ std::vector<simgrid::s4u::Link*>{link}, true));
+ }
+}
\ No newline at end of file
XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_full, surf, "Routing part of surf");
-#define TO_ROUTE_FULL(i, j) routing_table_[(i) + (j)*table_size]
-
namespace simgrid {
namespace kernel {
namespace routing {
-void FullZone::do_seal()
+void FullZone::check_routing_table()
{
unsigned int table_size = get_table_size();
+ /* assure routing_table is table_size X table_size */
+ if (routing_table_.size() != table_size) {
+ routing_table_.resize(table_size);
+ for (auto& j : routing_table_) {
+ j.resize(table_size);
+ }
+ }
+}
- /* Create table if needed */
- if (routing_table_.empty())
- routing_table_.resize(table_size * table_size, nullptr);
-
+void FullZone::do_seal()
+{
+ check_routing_table();
/* Add the loopback if needed */
if (get_network_model()->loopback_ && get_hierarchy() == RoutingMode::base) {
- for (unsigned int i = 0; i < table_size; i++) {
- Route* route = TO_ROUTE_FULL(i, i);
+ for (unsigned int i = 0; i < get_table_size(); i++) {
+ auto& route = routing_table_[i][i];
if (not route) {
- route = new Route();
+ route.reset(new Route());
route->link_list_.push_back(get_network_model()->loopback_);
- TO_ROUTE_FULL(i, i) = route;
}
}
}
}
-FullZone::~FullZone()
-{
- /* Delete routing table */
- for (auto const* route : routing_table_)
- delete route;
-}
-
void FullZone::get_local_route(NetPoint* src, NetPoint* dst, Route* res, double* lat)
{
XBT_DEBUG("full getLocalRoute from %s[%u] to %s[%u]", src->get_cname(), src->id(), dst->get_cname(), dst->id());
- unsigned int table_size = get_table_size();
- const Route* e_route = TO_ROUTE_FULL(src->id(), dst->id());
+ const auto& e_route = routing_table_[src->id()][dst->id()];
if (e_route != nullptr) {
res->gw_src_ = e_route->gw_src_;
{
add_route_check_params(src, dst, gw_src, gw_dst, link_list, symmetrical);
- unsigned int table_size = get_table_size();
-
- if (routing_table_.empty())
- routing_table_.resize(table_size * table_size, nullptr);
+ check_routing_table();
/* Check that the route does not already exist */
if (gw_dst && gw_src) // inter-zone route (to adapt the error message, if any)
- xbt_assert(nullptr == TO_ROUTE_FULL(src->id(), dst->id()),
+ xbt_assert(nullptr == routing_table_[src->id()][dst->id()],
"The route between %s@%s and %s@%s already exists (Rq: routes are symmetrical by default).",
src->get_cname(), gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname());
else
- xbt_assert(nullptr == TO_ROUTE_FULL(src->id(), dst->id()),
+ xbt_assert(nullptr == routing_table_[src->id()][dst->id()],
"The route between %s and %s already exists (Rq: routes are symmetrical by default).", src->get_cname(),
dst->get_cname());
/* Add the route to the base */
- TO_ROUTE_FULL(src->id(), dst->id()) = new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, true);
+ routing_table_[src->id()][dst->id()] =
+ std::unique_ptr<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, true));
if (symmetrical && src != dst) {
if (gw_dst && gw_src) {
}
if (gw_dst && gw_src) // inter-zone route (to adapt the error message, if any)
xbt_assert(
- nullptr == TO_ROUTE_FULL(dst->id(), src->id()),
+ nullptr == routing_table_[dst->id()][src->id()],
"The route between %s@%s and %s@%s already exists. You should not declare the reverse path as symmetrical.",
dst->get_cname(), gw_dst->get_cname(), src->get_cname(), gw_src->get_cname());
else
- xbt_assert(nullptr == TO_ROUTE_FULL(dst->id(), src->id()),
+ xbt_assert(nullptr == routing_table_[dst->id()][src->id()],
"The route between %s and %s already exists. You should not declare the reverse path as symmetrical.",
dst->get_cname(), src->get_cname());
- TO_ROUTE_FULL(dst->id(), src->id()) = new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, false);
+ routing_table_[dst->id()][src->id()] =
+ std::unique_ptr<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, false));
}
}
} // namespace routing
--- /dev/null
+/* Copyright (c) 2017-2021. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "catch.hpp"
+
+#include "simgrid/kernel/routing/FullZone.hpp"
+#include "simgrid/kernel/routing/NetPoint.hpp"
+#include "simgrid/s4u/Engine.hpp"
+#include "simgrid/s4u/Host.hpp"
+#include "simgrid/s4u/NetZone.hpp"
+#include "src/surf/network_interface.hpp" //LinkImpl
+
+namespace {
+class EngineWrapper {
+ int argc = 1;
+ char* argv;
+ simgrid::s4u::Engine e;
+
+public:
+ explicit EngineWrapper(std::string name) : argv(&name[0]), e(&argc, &argv) {}
+};
+} // namespace
+
+TEST_CASE("kernel::routing::FullZone: Creating Zone", "")
+{
+ EngineWrapper e("test");
+
+ REQUIRE(simgrid::s4u::create_full_zone("test"));
+}
+
+TEST_CASE("kernel::routing::FullZone: mix new routes and hosts", "[bug]")
+{
+ EngineWrapper e("test");
+ auto* zone = simgrid::s4u::create_full_zone("test");
+
+ const simgrid::s4u::Host* nic = zone->create_host("nic", 1e9)->seal();
+ simgrid::s4u::Link* link = zone->create_link("my_link", 1e6)->seal();
+ for (int i = 0; i < 10; i++) {
+ std::string cpu_name = "CPU" + std::to_string(i);
+ const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
+ REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
+ std::vector<simgrid::s4u::Link*>{link}, true));
+ }
+}
\ No newline at end of file
REQUIRE(route.link_list_[1]->get_name() == "link2");
}
}
+
+TEST_CASE("kernel::routing::StarZone: mix new routes and hosts", "")
+{
+ EngineWrapper e("test");
+ auto* zone = simgrid::s4u::create_star_zone("test");
+
+ simgrid::s4u::Link* link = zone->create_link("my_link", 1e6)->seal();
+ for (int i = 0; i < 10; i++) {
+ std::string cpu_name = "CPU" + std::to_string(i);
+ const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
+ REQUIRE_NOTHROW(
+ zone->add_route(cpu->get_netpoint(), nullptr, nullptr, nullptr, std::vector<simgrid::s4u::Link*>{link}, true));
+ }
+}
# New tests should use the Catch Framework
set(UNIT_TESTS src/xbt/unit-tests_main.cpp
src/kernel/resource/profile/Profile_test.cpp
+ src/kernel/routing/DijkstraZone_test.cpp
src/kernel/routing/DragonflyZone_test.cpp
src/kernel/routing/FatTreeZone_test.cpp
+ src/kernel/routing/FloydZone_test.cpp
+ src/kernel/routing/FullZone_test.cpp
src/kernel/routing/StarZone_test.cpp
src/kernel/routing/TorusZone_test.cpp
src/xbt/config_test.cpp