Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Link: Non-linear constraints
authorBruno Donassolo <bruno.donassolo@inria.fr>
Mon, 5 Jul 2021 12:36:12 +0000 (14:36 +0200)
committerBruno Donassolo <bruno.donassolo@inria.fr>
Thu, 15 Jul 2021 09:31:49 +0000 (11:31 +0200)
Add non-linear constraints to links.
Similar to disks, user can use a callback to dynamically change the
link's capacity based on the number of flows sharing it.
Only traffic explicit generated by the user is considered as active
flow, so cross-traffic communications aren't taken into account.

Extend s4u::Link::sharing_policy
- New type: NONLINEAR

Example: examples/cpp/network-nonlinear/

18 files changed:
MANIFEST.in
examples/cpp/CMakeLists.txt
examples/cpp/io-degradation/s4u-io-degradation.cpp
examples/cpp/network-nonlinear/s4u-network-nonlinear.cpp [new file with mode: 0644]
examples/cpp/network-nonlinear/s4u-network-nonlinear.tesh [new file with mode: 0644]
include/simgrid/s4u/Link.hpp
src/kernel/resource/DiskImpl.cpp
src/kernel/routing/WifiZone.cpp
src/s4u/s4u_Link.cpp
src/surf/LinkImpl.cpp
src/surf/LinkImpl.hpp
src/surf/LinkImplIntf.hpp
src/surf/SplitDuplexLinkImpl.cpp
src/surf/SplitDuplexLinkImpl.hpp
src/surf/network_cm02.cpp
src/surf/network_ns3.cpp
src/surf/network_ns3.hpp
src/surf/ptask_L07.cpp

index d35fde7..c7e3c41 100644 (file)
@@ -280,6 +280,8 @@ include examples/cpp/mc-failing-assert/s4u-mc-failing-assert.cpp
 include examples/cpp/mc-failing-assert/s4u-mc-failing-assert.tesh
 include examples/cpp/network-factors/s4u-network-factors.cpp
 include examples/cpp/network-factors/s4u-network-factors.tesh
+include examples/cpp/network-nonlinear/s4u-network-nonlinear.cpp
+include examples/cpp/network-nonlinear/s4u-network-nonlinear.tesh
 include examples/cpp/network-ns3-wifi/s4u-network-ns3-wifi.cpp
 include examples/cpp/network-ns3-wifi/s4u-network-ns3-wifi.tesh
 include examples/cpp/network-ns3/3hosts_2links_d.xml
index dfb3628..94c2f8f 100644 (file)
@@ -80,7 +80,7 @@ foreach (example actor-create actor-daemon actor-exiting actor-join actor-kill
                  replay-comm replay-io
                  routing-get-clusters
                  synchro-barrier synchro-condition-variable synchro-condition-variable-waituntil synchro-mutex synchro-semaphore
-                 clusters-multicpu network-factors)
+                 clusters-multicpu network-factors network-nonlinear)
 
   # Use default source file unless specified otherwise
   if(NOT DEFINED _${example}_sources)
index 30ae4aa..834872a 100644 (file)
@@ -66,7 +66,7 @@ static void host()
  * @param capacity Resource current capacity in SimGrid
  * @param n Number of activities sharing this resource
  */
-static double ssd_dynamic_sharing(const sg4::Disk* disk, const std::string& op, double capacity, int n)
+static double ssd_dynamic_sharing(const sg4::Disk* /*disk*/, const std::string& op, double capacity, int n)
 {
   /* measurements for SSD disks */
   using DiskCapacity                                                   = std::unordered_map<int, double>;
@@ -107,7 +107,7 @@ static double ssd_dynamic_sharing(const sg4::Disk* disk, const std::string& op,
  * @param capacity Resource current capacity in SimGrid
  * @param n Number of activities sharing this resource
  */
-static double sata_dynamic_sharing(const sg4::Disk* disk, double capacity, int n)
+static double sata_dynamic_sharing(const sg4::Disk* /*disk*/, double capacity, int n)
 {
   capacity = 68.3 - 1.7 * n;
   // XBT_INFO("Disk %s, read operation between %d flows, capacity %lf", disk->get_cname(), n, capacity);
diff --git a/examples/cpp/network-nonlinear/s4u-network-nonlinear.cpp b/examples/cpp/network-nonlinear/s4u-network-nonlinear.cpp
new file mode 100644 (file)
index 0000000..66332a1
--- /dev/null
@@ -0,0 +1,149 @@
+/* Copyright (c) 2010-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. */
+
+/* This example shows how to simulate a non-linear resource sharing for
+ * network links.
+ */
+
+#include <simgrid/s4u.hpp>
+
+namespace sg4 = simgrid::s4u;
+
+XBT_LOG_NEW_DEFAULT_CATEGORY(s4u_network_nonlinear, "Messages specific for this s4u example");
+
+/*************************************************************************************************/
+class Sender {
+  int messages_count; /* - number of messages */
+  int msg_size = 1e6; /* - message size in bytes */
+
+public:
+  explicit Sender(int count) : messages_count(count) {}
+  void operator()() const
+  {
+    // sphinx-doc: init-begin (this line helps the doc to build; ignore it)
+    /* Vector in which we store all ongoing communications */
+    std::vector<sg4::CommPtr> pending_comms;
+
+    /* Make a vector of the mailboxes to use */
+    sg4::Mailbox* mbox = sg4::Mailbox::by_name("receiver");
+    // sphinx-doc: init-end
+
+    /* Start dispatching all messages to receiver */
+    for (int i = 0; i < messages_count; i++) {
+      std::string msg_content = std::string("Message ") + std::to_string(i);
+      // Copy the data we send: the 'msg_content' variable is not a stable storage location.
+      // It will be destroyed when this actor leaves the loop, ie before the receiver gets it
+      auto* payload           = new std::string(msg_content);
+      unsigned long long size = msg_size * (i + 1);
+      XBT_INFO("Send '%s' to '%s, msg size: %llu'", msg_content.c_str(), mbox->get_cname(), size);
+
+      /* Create a communication representing the ongoing communication, and store it in pending_comms */
+      sg4::CommPtr comm = mbox->put_async(payload, size);
+      pending_comms.push_back(comm);
+    }
+
+    XBT_INFO("Done dispatching all messages");
+
+    /* Now that all message exchanges were initiated, wait for their completion in one single call */
+    sg4::Comm::wait_all(pending_comms);
+    // sphinx-doc: put-end
+
+    XBT_INFO("Goodbye now!");
+  }
+};
+
+/* Receiver actor expects 1 argument: number of messages to be received */
+class Receiver {
+  sg4::Mailbox* mbox;
+  int messages_count = 10; /* - number of messages */
+
+public:
+  explicit Receiver(int count) : messages_count(count) { mbox = sg4::Mailbox::by_name("receiver"); }
+  void operator()()
+  {
+    /* Vector in which we store all incoming msgs */
+    std::vector<std::unique_ptr<std::string*>> pending_msgs;
+    std::vector<sg4::CommPtr> pending_comms;
+
+    XBT_INFO("Wait for %d messages asynchronously", messages_count);
+    for (int i = 0; i < messages_count; i++) {
+      pending_msgs.push_back(std::make_unique<std::string*>());
+      pending_comms.emplace_back(mbox->get_async<std::string>(pending_msgs[i].get()));
+    }
+    while (not pending_comms.empty()) {
+      ssize_t index    = sg4::Comm::wait_any(pending_comms);
+      std::string* msg = *pending_msgs[index];
+      XBT_INFO("I got '%s'.", msg->c_str());
+      /* cleanup memory and remove from vectors */
+      delete msg;
+      pending_comms.erase(pending_comms.begin() + index);
+      pending_msgs.erase(pending_msgs.begin() + index);
+    }
+  }
+};
+
+/*************************************************************************************************/
+/** @brief Non-linear resource sharing for links
+ *
+ * Note that the callback is called twice in this example:
+ * 1) link UP: with the number of active flows (from 9 to 1)
+ * 2) link DOWN: with 0 active flows. A crosstraffic communication is happing
+ * in the down link, but it's not considered as an active flow.
+ */
+static double link_nonlinear(const sg4::Link* link, double capacity, int n)
+{
+  /* emulates a degradation in link according to the number of flows
+   * you probably want something more complex than that and based on real
+   * experiments */
+  capacity = std::min(capacity, capacity * (1.0 - (n - 1) / 10.0));
+  XBT_INFO("Link %s, %d active communications, new capacity %lf", link->get_cname(), n, capacity);
+  return capacity;
+}
+
+/** @brief Create a simple 2-hosts platform */
+static void load_platform()
+{
+  /* Creates the platform
+   *  ________                 __________
+   * | Sender |===============| Receiver |
+   * |________|    Link1      |__________|
+   */
+  auto* zone     = sg4::create_full_zone("Zone1");
+  auto* sender   = zone->create_host("sender", 1)->seal();
+  auto* receiver = zone->create_host("receiver", 1)->seal();
+
+  auto* link = zone->create_split_duplex_link("link1", 1e6);
+  /* setting same callbacks (could be different) for link UP/DOWN in split-duplex link */
+  link->get_link_up()->set_sharing_policy(
+      sg4::Link::SharingPolicy::NONLINEAR,
+      std::bind(&link_nonlinear, link->get_link_up(), std::placeholders::_1, std::placeholders::_2));
+  link->get_link_down()->set_sharing_policy(
+      sg4::Link::SharingPolicy::NONLINEAR,
+      std::bind(&link_nonlinear, link->get_link_down(), std::placeholders::_1, std::placeholders::_2));
+  link->set_latency(10e-6)->seal();
+
+  /* create routes between nodes */
+  zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
+                  {{link, sg4::LinkInRoute::Direction::UP}}, true);
+  zone->seal();
+
+  /* create actors Sender/Receiver */
+  sg4::Actor::create("receiver", receiver, Receiver(9));
+  sg4::Actor::create("sender", sender, Sender(9));
+}
+
+/*************************************************************************************************/
+int main(int argc, char* argv[])
+{
+  sg4::Engine e(&argc, argv);
+
+  /* create platform */
+  load_platform();
+
+  /* runs the simulation */
+  e.run();
+
+  return 0;
+}
diff --git a/examples/cpp/network-nonlinear/s4u-network-nonlinear.tesh b/examples/cpp/network-nonlinear/s4u-network-nonlinear.tesh
new file mode 100644 (file)
index 0000000..a4ece34
--- /dev/null
@@ -0,0 +1,42 @@
+$ ${bindir:=.}/s4u-network-nonlinear "--log=root.fmt:[%10.6r]%e(%i:%a@%h)%e%m%n"
+>[  0.000000] (1:receiver@receiver) Wait for 9 messages asynchronously
+>[  0.000000] (2:sender@sender) Send 'Message 0' to 'receiver, msg size: 1000000'
+>[  0.000000] (2:sender@sender) Send 'Message 1' to 'receiver, msg size: 2000000'
+>[  0.000000] (2:sender@sender) Send 'Message 2' to 'receiver, msg size: 3000000'
+>[  0.000000] (2:sender@sender) Send 'Message 3' to 'receiver, msg size: 4000000'
+>[  0.000000] (2:sender@sender) Send 'Message 4' to 'receiver, msg size: 5000000'
+>[  0.000000] (2:sender@sender) Send 'Message 5' to 'receiver, msg size: 6000000'
+>[  0.000000] (2:sender@sender) Send 'Message 6' to 'receiver, msg size: 7000000'
+>[  0.000000] (2:sender@sender) Send 'Message 7' to 'receiver, msg size: 8000000'
+>[  0.000000] (2:sender@sender) Send 'Message 8' to 'receiver, msg size: 9000000'
+>[  0.000000] (2:sender@sender) Done dispatching all messages
+>[  0.000000] (0:maestro@) Link link1_UP, 0 active communications, new capacity 1000000.000000
+>[  0.000000] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[  0.000130] (0:maestro@) Link link1_UP, 9 active communications, new capacity 200000.000000
+>[  0.000130] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[ 46.391883] (1:receiver@receiver) I got 'Message 0'.
+>[ 46.391883] (0:maestro@) Link link1_UP, 8 active communications, new capacity 300000.000000
+>[ 46.391883] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[ 73.883292] (1:receiver@receiver) I got 'Message 1'.
+>[ 73.883292] (0:maestro@) Link link1_UP, 7 active communications, new capacity 400000.000000
+>[ 73.883292] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[ 91.924529] (1:receiver@receiver) I got 'Message 2'.
+>[ 91.924529] (0:maestro@) Link link1_UP, 6 active communications, new capacity 500000.000000
+>[ 91.924529] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[104.295663] (1:receiver@receiver) I got 'Message 3'.
+>[104.295663] (0:maestro@) Link link1_UP, 5 active communications, new capacity 600000.000000
+>[104.295663] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[112.886728] (1:receiver@receiver) I got 'Message 4'.
+>[112.886728] (0:maestro@) Link link1_UP, 4 active communications, new capacity 700000.000000
+>[112.886728] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[118.777744] (1:receiver@receiver) I got 'Message 5'.
+>[118.777744] (0:maestro@) Link link1_UP, 3 active communications, new capacity 800000.000000
+>[118.777744] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[122.643724] (1:receiver@receiver) I got 'Message 6'.
+>[122.643724] (0:maestro@) Link link1_UP, 2 active communications, new capacity 900000.000000
+>[122.643724] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[124.934674] (1:receiver@receiver) I got 'Message 7'.
+>[124.934674] (0:maestro@) Link link1_UP, 1 active communications, new capacity 1000000.000000
+>[124.934674] (0:maestro@) Link link1_DOWN, 0 active communications, new capacity 1000000.000000
+>[125.965602] (1:receiver@receiver) I got 'Message 8'.
+>[125.965602] (2:sender@sender) Goodbye now!
index 7473903..bcd91af 100644 (file)
@@ -42,7 +42,7 @@ protected:
   kernel::resource::LinkImplIntf* const pimpl_;
 
 public:
-  enum class SharingPolicy { WIFI = 3, SPLITDUPLEX = 2, SHARED = 1, FATPIPE = 0 };
+  enum class SharingPolicy { NONLINEAR = 4, WIFI = 3, SPLITDUPLEX = 2, SHARED = 1, FATPIPE = 0 };
 
   kernel::resource::LinkImpl* get_impl() const;
 
@@ -79,7 +79,7 @@ public:
   Link* set_latency(const std::string& value);
 
   /** @brief Describes how the link is shared between flows */
-  Link* set_sharing_policy(SharingPolicy policy);
+  Link* set_sharing_policy(SharingPolicy policy, const NonLinearResourceCb& cb = {});
   SharingPolicy get_sharing_policy() const;
 
   /** Setup the profile with states events (ON or OFF). The profile must contain boolean values. */
index a027ee7..acd3ff3 100644 (file)
@@ -127,7 +127,6 @@ constexpr kernel::lmm::Constraint::SharingPolicy to_maxmin_policy(s4u::Disk::Sha
   switch (policy) {
     case s4u::Disk::SharingPolicy::NONLINEAR:
       return kernel::lmm::Constraint::SharingPolicy::NONLINEAR;
-    case s4u::Disk::SharingPolicy::LINEAR:
     default:
       return kernel::lmm::Constraint::SharingPolicy::SHARED;
   }
index 3c42017..26df5eb 100644 (file)
@@ -53,7 +53,7 @@ s4u::Link* WifiZone::create_link(const std::string& name, const std::vector<doub
              "WIFI netzone %s contains more than one link. Please only declare one, the wifi link.", get_cname());
 
   wifi_link_ = get_network_model()->create_wifi_link(name, bandwidths);
-  wifi_link_->set_sharing_policy(s4u::Link::SharingPolicy::WIFI);
+  wifi_link_->set_sharing_policy(s4u::Link::SharingPolicy::WIFI, {});
   return wifi_link_->get_iface();
 }
 } // namespace routing
index 2e2a3ba..c4c179c 100644 (file)
@@ -102,13 +102,13 @@ Link* Link::set_bandwidth(double value)
   return this;
 }
 
-Link* Link::set_sharing_policy(Link::SharingPolicy policy)
+Link* Link::set_sharing_policy(Link::SharingPolicy policy, const NonLinearResourceCb& cb)
 {
   if (policy == SharingPolicy::SPLITDUPLEX)
     throw std::invalid_argument(std::string("Impossible to set split-duplex for the link: ") + get_name() +
                                 std::string(". Use NetZone::create_split_duplex_link."));
 
-  kernel::actor::simcall([this, policy] { pimpl_->set_sharing_policy(policy); });
+  kernel::actor::simcall([this, policy, &cb] { pimpl_->set_sharing_policy(policy, cb); });
   return this;
 }
 Link::SharingPolicy Link::get_sharing_policy() const
index 6b66ce4..ecbf1ac 100644 (file)
@@ -43,14 +43,24 @@ bool LinkImpl::is_used() const
   return get_model()->get_maxmin_system()->constraint_used(get_constraint());
 }
 
-void LinkImpl::set_sharing_policy(s4u::Link::SharingPolicy policy)
+constexpr kernel::lmm::Constraint::SharingPolicy to_maxmin_policy(s4u::Link::SharingPolicy policy)
 {
-  lmm::Constraint::SharingPolicy ct_policy = lmm::Constraint::SharingPolicy::SHARED;
-  if (policy == s4u::Link::SharingPolicy::FATPIPE)
-    ct_policy = lmm::Constraint::SharingPolicy::FATPIPE;
-  get_constraint()->set_sharing_policy(ct_policy, {});
+  switch (policy) {
+    case s4u::Link::SharingPolicy::NONLINEAR:
+      return kernel::lmm::Constraint::SharingPolicy::NONLINEAR;
+    case s4u::Link::SharingPolicy::FATPIPE:
+      return kernel::lmm::Constraint::SharingPolicy::FATPIPE;
+    default:
+      return kernel::lmm::Constraint::SharingPolicy::SHARED;
+  }
+}
+
+void LinkImpl::set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb)
+{
+  get_constraint()->set_sharing_policy(to_maxmin_policy(policy), cb);
   sharing_policy_ = policy;
 }
+
 s4u::Link::SharingPolicy LinkImpl::get_sharing_policy() const
 {
   return sharing_policy_;
index 7c25c28..d560879 100644 (file)
@@ -32,6 +32,9 @@ protected:
   LinkImpl& operator=(const LinkImpl&) = delete;
   ~LinkImpl() override                 = default; // Use destroy() instead of this destructor.
 
+  Metric latency_   = {0.0, 1, nullptr};
+  Metric bandwidth_ = {1.0, 1, nullptr};
+
 public:
   void destroy(); // Must be called instead of the destructor
 
@@ -48,7 +51,7 @@ public:
   double get_latency() const override { return latency_.peak * latency_.scale; }
 
   /** @brief The sharing policy */
-  void set_sharing_policy(s4u::Link::SharingPolicy policy) override;
+  void set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb) override;
   s4u::Link::SharingPolicy get_sharing_policy() const override;
 
   /** @brief Check if the Link is used */
@@ -69,9 +72,6 @@ public:
   void set_latency_profile(kernel::profile::Profile* profile) override;
 
   void set_concurrency_limit(int limit) const override;
-
-  Metric latency_   = {0.0, 1, nullptr};
-  Metric bandwidth_ = {1.0, 1, nullptr};
 };
 
 } // namespace resource
index c9d3dac..aac4b84 100644 (file)
@@ -38,7 +38,7 @@ public:
   virtual void set_latency(double value) = 0;
 
   /** @brief The sharing policy */
-  virtual void set_sharing_policy(s4u::Link::SharingPolicy policy) = 0;
+  virtual void set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb) = 0;
   virtual s4u::Link::SharingPolicy get_sharing_policy() const      = 0;
 
   /* setup the profile file with bandwidth events (peak speed changes due to external load).
index 2b2b003..6e3608f 100644 (file)
@@ -25,7 +25,7 @@ bool SplitDuplexLinkImpl::is_used() const
   xbt_die("Impossible to call is_used() in split-duplex links. Call it for each individual link.");
 }
 
-void SplitDuplexLinkImpl::set_sharing_policy(s4u::Link::SharingPolicy policy)
+void SplitDuplexLinkImpl::set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb)
 {
   xbt_die("Impossible to change sharing policy of split-duplex links");
 }
index e8c1721..4842f08 100644 (file)
@@ -47,7 +47,7 @@ public:
   void set_latency(double value) override;
 
   /** @brief The sharing policy */
-  void set_sharing_policy(s4u::Link::SharingPolicy policy) override;
+  void set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb) override;
   s4u::Link::SharingPolicy get_sharing_policy() const override { return s4u::Link::SharingPolicy::SPLITDUPLEX; }
 
   /** @brief Get link composing this split-duplex link */
index 3949779..9cafb25 100644 (file)
@@ -88,7 +88,7 @@ NetworkCm02Model::NetworkCm02Model(const std::string& name) : NetworkModel(name)
 
   set_maxmin_system(new lmm::System(select));
   loopback_ = create_link("__loopback__", {config::get_value<double>("network/loopback-bw")});
-  loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE);
+  loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE, {});
   loopback_->set_latency(config::get_value<double>("network/loopback-lat"));
   loopback_->seal();
 }
index 81839ef..e8f7300 100644 (file)
@@ -345,7 +345,7 @@ LinkImpl* NetworkNS3Model::create_link(const std::string& name, const std::vecto
 LinkImpl* NetworkNS3Model::create_wifi_link(const std::string& name, const std::vector<double>& bandwidths)
 {
   auto* link = create_link(name, bandwidths);
-  link->set_sharing_policy(s4u::Link::SharingPolicy::WIFI);
+  link->set_sharing_policy(s4u::Link::SharingPolicy::WIFI, {});
   return link;
 }
 
@@ -474,7 +474,7 @@ void LinkNS3::set_latency(double latency)
   latency_.peak = latency;
 }
 
-void LinkNS3::set_sharing_policy(s4u::Link::SharingPolicy policy)
+void LinkNS3::set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb)
 {
   sharing_policy_ = policy;
 }
index c0a8e11..398de6e 100644 (file)
@@ -39,7 +39,7 @@ public:
   void set_latency(double) override;
   void set_bandwidth_profile(profile::Profile* profile) override;
   void set_latency_profile(profile::Profile* profile) override;
-  void set_sharing_policy(s4u::Link::SharingPolicy policy) override;
+  void set_sharing_policy(s4u::Link::SharingPolicy policy, const s4u::NonLinearResourceCb& cb) override;
   s4u::Link::SharingPolicy get_sharing_policy() const override { return sharing_policy_; }
 };
 
index aa9d9ff..69efd74 100644 (file)
@@ -62,7 +62,7 @@ NetworkL07Model::NetworkL07Model(const std::string& name, HostL07Model* hmodel,
 {
   set_maxmin_system(sys);
   loopback_ = create_link("__loopback__", {simgrid::config::get_value<double>("network/loopback-bw")});
-  loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE);
+  loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE, {});
   loopback_->set_latency(simgrid::config::get_value<double>("network/loopback-lat"));
   loopback_->seal();
 }