Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
New netzone: Star Zone
authorBruno Donassolo <bruno.donassolo@inria.fr>
Fri, 9 Apr 2021 17:46:42 +0000 (19:46 +0200)
committerBruno Donassolo <bruno.donassolo@inria.fr>
Wed, 14 Apr 2021 09:00:34 +0000 (11:00 +0200)
Implements a netzone following a star topology.
Components inside the Star topology are connected by default (through no
links), users can add routes using the NetZone::add_route method:
- netpoint -> nullptr(*): links used in all outgoing communications
- nullptr(*) -> netpoint: links used in all incoming communication
- netpoint -> netpoint: loopback

Duplicated links in a route inside the Star Zone are removed.

Added UTs for StarZone, some tests are disabled since they check the
xbt_assert and would stop the test execution.

MANIFEST.in
include/simgrid/kernel/routing/StarZone.hpp [new file with mode: 0644]
include/simgrid/s4u/NetZone.hpp
src/kernel/routing/StarZone.cpp [new file with mode: 0644]
src/kernel/routing/StarZone_test.cpp [new file with mode: 0644]
tools/cmake/DefinePackages.cmake
tools/cmake/Tests.cmake

index f45069b..8898a5b 100644 (file)
@@ -1972,6 +1972,7 @@ include include/simgrid/kernel/routing/FullZone.hpp
 include include/simgrid/kernel/routing/NetPoint.hpp
 include include/simgrid/kernel/routing/NetZoneImpl.hpp
 include include/simgrid/kernel/routing/RoutedZone.hpp
+include include/simgrid/kernel/routing/StarZone.hpp
 include include/simgrid/kernel/routing/TorusZone.hpp
 include include/simgrid/kernel/routing/VivaldiZone.hpp
 include include/simgrid/kernel/routing/WifiZone.hpp
@@ -2205,6 +2206,8 @@ include src/kernel/routing/FullZone.cpp
 include src/kernel/routing/NetPoint.cpp
 include src/kernel/routing/NetZoneImpl.cpp
 include src/kernel/routing/RoutedZone.cpp
+include src/kernel/routing/StarZone.cpp
+include src/kernel/routing/StarZone_test.cpp
 include src/kernel/routing/TorusZone.cpp
 include src/kernel/routing/VivaldiZone.cpp
 include src/kernel/routing/WifiZone.cpp
diff --git a/include/simgrid/kernel/routing/StarZone.hpp b/include/simgrid/kernel/routing/StarZone.hpp
new file mode 100644 (file)
index 0000000..2f27bf2
--- /dev/null
@@ -0,0 +1,89 @@
+/* Copyright (c) 2013-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. */
+
+#ifndef SIMGRID_KERNEL_ROUTING_STARZONE_HPP_
+#define SIMGRID_KERNEL_ROUTING_STARZONE_HPP_
+
+#include <simgrid/kernel/routing/NetZoneImpl.hpp>
+
+#include <unordered_map>
+#include <unordered_set>
+
+namespace simgrid {
+namespace kernel {
+namespace routing {
+
+/** @ingroup ROUTING_API
+ *  @brief NetZone where components are connected following a star topology
+ *
+ *  Star zones have a collection of private links that interconnect their components.
+ *  By default, all components inside the star zone are interconnected with no links.
+ *
+ *  You can use add_route to set the links to be used during communications, 3
+ *  configurations are possible:
+ *  - (*(all) -> Component): links used in the outgoing communications from component (UP).
+ *  - (Component -> *(all)): links used in ine ingoing communication to component (DOWN).
+ *  - Loopback: links connecting the component to itself.
+ *
+ *  @note: Communications between nodes inside the Star zone cannot have duplicate links.
+ *         All duplicated links are automatically removed when building the route.
+ *
+ * \verbatim
+ *   (outer world)
+ *         |
+ *     l3 /|\ l4
+ *       / | \     <-- links
+ *      +  |  +
+ *  l0 / l1|   \l2
+ *    /    |    \
+ *   A     B     C <-- netpoints
+ * \endverbatim
+ *
+ *  So, a communication from the host A to the host B goes through the following links:
+ *   <tt>l0, l3, l1.</tt>
+ *
+ *  In the same way, a communication from host A to nodes outside this netzone will
+ *  use the same links <tt> l0, l3. </tt>
+ *
+ *  \verbatim
+ *   (outer world)
+ *         |
+ *   ======+====== <-- backbone
+ *   |   |   |   |
+ * l0| l1| l2| l4| <-- links
+ *   |   |   |   |
+ *   A   B   C   D <-- netpoints
+ * \endverbatim
+ *
+ *  In this case, a communication from A to B goes through the links: <tt> l0, backbone, l1. </tt>
+ *  Note that the backbone only appears once in the link list.
+ */
+
+class StarZone : public NetZoneImpl {
+
+public:
+  explicit StarZone(const std::string& name);
+
+  void get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* route, double* latency) override;
+  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;
+
+  void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
+                 const std::vector<kernel::resource::LinkImpl*>& link_list, bool symmetrical) override;
+  void do_seal() override;
+
+private:
+  /** @brief Auxiliary method to add links to a route */
+  void add_links_to_route(const std::vector<resource::LinkImpl*>& links, RouteCreationArgs* route, double* latency,
+                          std::unordered_set<resource::LinkImpl*>& added_links);
+  std::unordered_map<unsigned int, std::vector<resource::LinkImpl*>> links_up_;
+  std::unordered_map<unsigned int, std::vector<resource::LinkImpl*>> loopback_;
+  std::unordered_map<unsigned int, std::vector<resource::LinkImpl*>> links_down_;
+};
+} // namespace routing
+} // namespace kernel
+} // namespace simgrid
+
+#endif /* SIMGRID_KERNEL_ROUTING_STARZONE_HPP_ */
\ No newline at end of file
index 045a089..55ba9fa 100644 (file)
@@ -146,6 +146,7 @@ private:
 // External constructors so that the types (and the types of their content) remain hidden
 XBT_PUBLIC NetZone* create_full_zone(const std::string& name);
 XBT_PUBLIC NetZone* create_cluster_zone(const std::string& name);
+XBT_PUBLIC NetZone* create_star_zone(const std::string& name);
 XBT_PUBLIC NetZone* create_dijkstra_zone(const std::string& name, bool cache);
 XBT_PUBLIC NetZone* create_dragonfly_zone(const std::string& name);
 XBT_PUBLIC NetZone* create_empty_zone(const std::string& name);
diff --git a/src/kernel/routing/StarZone.cpp b/src/kernel/routing/StarZone.cpp
new file mode 100644 (file)
index 0000000..972da4e
--- /dev/null
@@ -0,0 +1,123 @@
+/* Copyright (c) 2009-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 "simgrid/kernel/routing/StarZone.hpp"
+#include "simgrid/kernel/routing/NetPoint.hpp"
+#include "simgrid/kernel/routing/RoutedZone.hpp"
+#include "src/surf/network_interface.hpp"
+#include "src/surf/xml/platf_private.hpp" // RouteCreationArgs and friends
+
+XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_route_star, surf, "Routing part of surf");
+
+namespace simgrid {
+namespace kernel {
+namespace routing {
+StarZone::StarZone(const std::string& name) : NetZoneImpl(name) {}
+
+void StarZone::add_links_to_route(const std::vector<resource::LinkImpl*>& links, RouteCreationArgs* route,
+                                  double* latency, std::unordered_set<resource::LinkImpl*>& added_links)
+{
+  for (auto* link : links) {
+    /* do not add duplicated links */
+    if (added_links.find(link) != added_links.end())
+      continue;
+    added_links.insert(link);
+    if (latency)
+      *latency += link->get_latency();
+    route->link_list.push_back(link);
+  }
+}
+
+void StarZone::get_local_route(NetPoint* src, NetPoint* dst, RouteCreationArgs* route, double* latency)
+{
+  XBT_VERB("StarZone getLocalRoute from '%s'[%u] to '%s'[%u]", src->get_cname(), src->id(), dst->get_cname(),
+           dst->id());
+
+  xbt_assert(((src == dst) and (loopback_.find(src->id()) != loopback_.end())) or
+                 (links_up_.find(src->id()) != links_up_.end()),
+             "StarZone routing (%s - %s): no link UP from source node. Did you use add_route() to set it?",
+             src->get_cname(), dst->get_cname());
+  xbt_assert(((src == dst) and (loopback_.find(dst->id()) != loopback_.end())) or
+                 (links_down_.find(dst->id()) != links_down_.end()),
+             "StarZone routing (%s - %s): no link DOWN to destination node. Did you use add_route() to set it?",
+             src->get_cname(), dst->get_cname());
+
+  std::unordered_set<resource::LinkImpl*> added_links;
+  /* loopback */
+  if ((src == dst) and (loopback_.find(src->id()) != loopback_.end())) {
+    add_links_to_route(loopback_[src->id()], route, latency, added_links);
+    return;
+  }
+
+  /* going UP */
+  add_links_to_route(links_up_[src->id()], route, latency, added_links);
+
+  /* going DOWN */
+  add_links_to_route(links_down_[dst->id()], route, latency, added_links);
+}
+
+void StarZone::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)
+{
+}
+
+void StarZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
+                         const std::vector<kernel::resource::LinkImpl*>& link_list, bool symmetrical)
+{
+  const char* src_name = src ? src->get_cname() : "nullptr";
+  const char* dst_name = dst ? dst->get_cname() : "nullptr";
+
+  xbt_assert((src == dst) or (not src and dst) or (src and not dst),
+             "Cannot add route from %s to %s. In a StarZone, route must be:  i) from source host to everyone, ii) from "
+             "everyone to a single host or iii) loopback, same source and destination",
+             src_name, dst_name);
+  xbt_assert((not symmetrical) or (symmetrical and src),
+             "Cannot add route from %s to %s. In a StarZone, symmetrical routes must be set from source to everyone "
+             "(not the contrary).",
+             src_name, dst_name);
+
+  /* loopback */
+  if (src == dst) {
+    loopback_[src->id()] = link_list;
+  } else {
+    /* src to everyone */
+    if (src) {
+      links_up_[src->id()] = link_list;
+      if (symmetrical) {
+        links_down_[src->id()] = link_list;
+        /* reverse it for down/symmetrical links */
+        std::reverse(links_down_[src->id()].begin(), links_down_[src->id()].end());
+      }
+    }
+    /* dst to everyone */
+    if (dst) {
+      links_down_[dst->id()] = link_list;
+    }
+  }
+  s4u::NetZone::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, link_list);
+}
+
+void StarZone::do_seal()
+{
+  /* add default empty links if nothing was configured by user */
+  for (auto const& node : get_vertices()) {
+    if ((links_up_.find(node->id()) == links_up_.end()) and (links_down_.find(node->id()) == links_down_.end())) {
+      links_down_[node->id()] = {};
+      links_up_[node->id()]   = {};
+    }
+  }
+}
+
+} // namespace routing
+} // namespace kernel
+
+namespace s4u {
+NetZone* create_star_zone(const std::string& name)
+{
+  return (new kernel::routing::StarZone(name))->get_iface();
+}
+} // namespace s4u
+
+} // namespace simgrid
diff --git a/src/kernel/routing/StarZone_test.cpp b/src/kernel/routing/StarZone_test.cpp
new file mode 100644 (file)
index 0000000..ef8fb3d
--- /dev/null
@@ -0,0 +1,205 @@
+/* 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/NetPoint.hpp"
+#include "simgrid/kernel/routing/StarZone.hpp"
+#include "simgrid/s4u/Engine.hpp"
+#include "simgrid/s4u/Host.hpp"
+#include "simgrid/s4u/NetZone.hpp"
+#include "src/surf/network_interface.hpp"
+#include "src/surf/surf_interface.hpp"    // create models
+#include "src/surf/xml/platf_private.hpp" // RouteCreationArgs and friends
+
+TEST_CASE("kernel::routing::StarZone: Creating Zone", "[creation]")
+{
+  int argc           = 1;
+  const char* argv[] = {"test"};
+
+  simgrid::s4u::Engine e(&argc, const_cast<char**>(argv));
+
+  REQUIRE(simgrid::s4u::create_star_zone("test"));
+}
+
+// One day we may be able to test contracts and asserts with catch2
+// https://github.com/catchorg/Catch2/issues/853
+TEST_CASE("kernel::routing::StarZone: Adding routes: assert", "[.][assert]")
+{
+  int argc           = 1;
+  const char* argv[] = {"test"};
+  simgrid::s4u::Engine e(&argc, const_cast<char**>(argv));
+  auto* zone      = new simgrid::kernel::routing::StarZone("test");
+  auto* netpoint1 = new simgrid::kernel::routing::NetPoint("netpoint1", simgrid::kernel::routing::NetPoint::Type::Host);
+  auto* netpoint2 = new simgrid::kernel::routing::NetPoint("netpoint2", simgrid::kernel::routing::NetPoint::Type::Host);
+
+  SECTION("Source and destination hosts: nullptr") { zone->add_route(nullptr, nullptr, nullptr, nullptr, {}, false); }
+
+  SECTION("Source nullptr and symmetrical true") { zone->add_route(nullptr, netpoint2, nullptr, nullptr, {}, true); }
+
+  SECTION("Source and destination set") { zone->add_route(netpoint1, netpoint2, nullptr, nullptr, {}, false); }
+}
+
+TEST_CASE("kernel::routing::StarZone: Get routes: assert", "[.][assert]")
+{
+  /* workaround to initialize things, they must be done in this particular order */
+  int argc           = 1;
+  const char* argv[] = {"test"};
+  simgrid::s4u::Engine e(&argc, const_cast<char**>(argv));
+  auto* zone = new simgrid::kernel::routing::StarZone("test");
+  surf_network_model_init_LegrandVelho();
+  surf_cpu_model_init_Cas01();
+
+  auto* host1 = zone->create_host("netpoint1", {100});
+  auto* host2 = zone->create_host("netpoint2", {100});
+  std::vector<simgrid::kernel::resource::LinkImpl*> links;
+  links.push_back(zone->create_link("link1", {100})->get_impl());
+  std::vector<simgrid::kernel::resource::LinkImpl*> links2;
+  links2.push_back(zone->create_link("link2", {100})->get_impl());
+
+  SECTION("Get route: no UP link")
+  {
+    zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true);
+    zone->add_route(nullptr, host2->get_netpoint(), nullptr, nullptr, links2, false);
+    double lat;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host2->get_netpoint(), host1->get_netpoint(), &route, &lat);
+  }
+
+  SECTION("Get route: no DOWN link")
+  {
+    zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, false);
+    zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true);
+    double lat;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host2->get_netpoint(), host1->get_netpoint(), &route, &lat);
+  }
+}
+
+TEST_CASE("kernel::routing::StarZone: Adding routes: valid", "")
+{
+  int argc           = 1;
+  const char* argv[] = {"test"};
+  simgrid::s4u::Engine e(&argc, const_cast<char**>(argv));
+  auto* zone     = new simgrid::kernel::routing::StarZone("test");
+  auto* netpoint = new simgrid::kernel::routing::NetPoint("netpoint1", simgrid::kernel::routing::NetPoint::Type::Host);
+
+  SECTION("Source set, destination nullptr, symmetrical true")
+  {
+    zone->add_route(netpoint, nullptr, nullptr, nullptr, {}, true);
+  }
+
+  SECTION("Source nullptr, destination set, symmetrical false")
+  {
+    zone->add_route(nullptr, netpoint, nullptr, nullptr, {}, false);
+  }
+
+  SECTION("Source set, destination nullptr, symmetrical false")
+  {
+    zone->add_route(netpoint, nullptr, nullptr, nullptr, {}, false);
+  }
+
+  SECTION("Source == destination") { zone->add_route(netpoint, netpoint, nullptr, nullptr, {}, false); }
+}
+
+TEST_CASE("kernel::routing::StarZone: Get routes", "")
+{
+  /* workaround to initialize things, they must be done in this particular order */
+  int argc           = 1;
+  const char* argv[] = {"test"};
+  simgrid::s4u::Engine e(&argc, const_cast<char**>(argv));
+  auto* zone = new simgrid::kernel::routing::StarZone("test");
+  surf_network_model_init_LegrandVelho();
+  surf_cpu_model_init_Cas01();
+
+  auto* host1 = zone->create_host("netpoint1", {100});
+  auto* host2 = zone->create_host("netpoint2", {100});
+
+  SECTION("Get route: no shared link")
+  {
+    std::vector<simgrid::kernel::resource::LinkImpl*> links;
+    links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
+    std::vector<simgrid::kernel::resource::LinkImpl*> links2;
+    links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
+    zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true);
+    zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true);
+    zone->seal();
+
+    double lat = 0.0;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host1->get_netpoint(), host2->get_netpoint(), &route, &lat);
+    REQUIRE(lat == 30);
+    REQUIRE(route.link_list.size() == 2);
+    REQUIRE(route.link_list[0]->get_name() == "link1");
+    REQUIRE(route.link_list[1]->get_name() == "link2");
+  }
+
+  SECTION("Get route: shared link(backbone)")
+  {
+    auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl();
+    std::vector<simgrid::kernel::resource::LinkImpl*> links;
+    links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
+    links.push_back(backbone);
+    std::vector<simgrid::kernel::resource::LinkImpl*> links2;
+    links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
+    links2.push_back(backbone);
+
+    zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true);
+    zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true);
+    zone->seal();
+
+    double lat = 0.0;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host1->get_netpoint(), host2->get_netpoint(), &route, &lat);
+    REQUIRE(lat == 130);
+    REQUIRE(route.link_list.size() == 3);
+    REQUIRE(route.link_list[0]->get_name() == "link1");
+    REQUIRE(route.link_list[1]->get_name() == "backbone");
+    REQUIRE(route.link_list[2]->get_name() == "link2");
+  }
+
+  SECTION("Get route: shared link(backbone)")
+  {
+    auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl();
+    std::vector<simgrid::kernel::resource::LinkImpl*> links;
+    links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
+    links.push_back(backbone);
+    std::vector<simgrid::kernel::resource::LinkImpl*> links2;
+    links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
+    links2.push_back(backbone);
+
+    zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true);
+    zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true);
+    zone->seal();
+
+    double lat = 0.0;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host1->get_netpoint(), host2->get_netpoint(), &route, &lat);
+    REQUIRE(lat == 130);
+    REQUIRE(route.link_list.size() == 3);
+    REQUIRE(route.link_list[0]->get_name() == "link1");
+    REQUIRE(route.link_list[1]->get_name() == "backbone");
+    REQUIRE(route.link_list[2]->get_name() == "link2");
+  }
+
+  SECTION("Get route: loopback")
+  {
+    auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl();
+    std::vector<simgrid::kernel::resource::LinkImpl*> links;
+    links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
+    links.push_back(backbone);
+
+    zone->add_route(host1->get_netpoint(), host1->get_netpoint(), nullptr, nullptr, links, true);
+    zone->seal();
+
+    double lat = 0.0;
+    simgrid::kernel::routing::RouteCreationArgs route;
+    zone->get_local_route(host1->get_netpoint(), host1->get_netpoint(), &route, &lat);
+    REQUIRE(lat == 110);
+    REQUIRE(route.link_list.size() == 2);
+    REQUIRE(route.link_list[0]->get_name() == "link1");
+    REQUIRE(route.link_list[1]->get_name() == "backbone");
+  }
+}
\ No newline at end of file
index f2c8d7e..231e6ab 100644 (file)
@@ -331,8 +331,9 @@ set(SURF_SRC
   src/kernel/routing/FullZone.cpp
   src/kernel/routing/NetPoint.cpp
   src/kernel/routing/NetZoneImpl.cpp
-  src/kernel/routing/TorusZone.cpp
   src/kernel/routing/RoutedZone.cpp
+  src/kernel/routing/StarZone.cpp
+  src/kernel/routing/TorusZone.cpp
   src/kernel/routing/VivaldiZone.cpp
   src/kernel/routing/WifiZone.cpp
 
@@ -726,6 +727,7 @@ set(headers_to_install
   include/simgrid/kernel/routing/NetPoint.hpp
   include/simgrid/kernel/routing/NetZoneImpl.hpp
   include/simgrid/kernel/routing/RoutedZone.hpp
+  include/simgrid/kernel/routing/StarZone.hpp
   include/simgrid/kernel/routing/TorusZone.hpp
   include/simgrid/kernel/routing/VivaldiZone.hpp
   include/simgrid/kernel/routing/WifiZone.hpp
index c6f7138..33f4d23 100644 (file)
@@ -124,6 +124,7 @@ ENDIF()
 # 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/StarZone_test.cpp
                 src/xbt/config_test.cpp
                 src/xbt/dict_test.cpp
                 src/xbt/dynar_test.cpp