From 19e1048a7009c4144b0f361ad85fb9dff44761ea Mon Sep 17 00:00:00 2001 From: Bruno Donassolo Date: Fri, 18 Jun 2021 15:11:57 +0200 Subject: [PATCH] Split-Duplex: new management 1. Huge commit to add support to Split-Duplex in S4U. - New interface: s4u::SplitDuplexLink 2. Allows its creation through the C++ interface without manually creating the link UP and DOWN. - NetZone::create_split_duplex_link 3. Changes in NetZone::add_route to allow the description of the direction in C++ interface - LinkInRoute: wrap around Link* to indicate the direction (UP/DOWN/NONE) for the link. - UP/DOWN are used to split-duplex links - NONE for other types (shared, wifi, fat-pipe) 4. Fix use of split-duplex links in symmetric routes in XML too. Now this code works, it will add the link1_DOWN as route to bob->alice. In the past, it would add link1_UP for bob->alice too. --- MANIFEST.in | 6 + docs/source/Platform_cpp.rst | 14 +- .../s4u-clusters-multicpu.cpp | 13 +- .../cpp/comm-serialize/s4u-comm-serialize.cpp | 9 +- .../network-factors/s4u-network-factors.cpp | 10 +- .../plugin-prodcons/s4u-plugin-prodcons.cpp | 7 +- examples/platforms/griffon.cpp | 10 +- examples/platforms/routing_cluster.cpp | 6 +- include/simgrid/forward.h | 3 + .../simgrid/kernel/routing/DijkstraZone.hpp | 2 +- include/simgrid/kernel/routing/FloydZone.hpp | 2 +- include/simgrid/kernel/routing/FullZone.hpp | 2 +- .../simgrid/kernel/routing/NetZoneImpl.hpp | 16 +- include/simgrid/kernel/routing/RoutedZone.hpp | 2 +- include/simgrid/kernel/routing/StarZone.hpp | 2 +- include/simgrid/s4u/Engine.hpp | 5 + include/simgrid/s4u/Link.hpp | 57 +++++++- include/simgrid/s4u/NetZone.hpp | 50 +++++-- src/bindings/lua/lua_platf.cpp | 12 +- src/kernel/EngineImpl.cpp | 5 + src/kernel/EngineImpl.hpp | 5 + src/kernel/routing/DijkstraZone.cpp | 10 +- src/kernel/routing/DijkstraZone_test.cpp | 2 +- src/kernel/routing/FloydZone.cpp | 12 +- src/kernel/routing/FloydZone_test.cpp | 2 +- src/kernel/routing/FullZone.cpp | 10 +- src/kernel/routing/FullZone_test.cpp | 2 +- src/kernel/routing/NetZoneImpl.cpp | 65 ++++++++- src/kernel/routing/RoutedZone.cpp | 8 +- src/kernel/routing/StarZone.cpp | 13 +- src/kernel/routing/StarZone_test.cpp | 65 +++++---- src/kernel/routing/VivaldiZone.cpp | 4 +- src/s4u/s4u_Engine.cpp | 8 + src/s4u/s4u_Link.cpp | 27 +++- src/s4u/s4u_Netzone.cpp | 44 ++++-- src/surf/LinkImpl.cpp | 137 ++++++++++++++++++ src/surf/LinkImpl.hpp | 81 +++++++++++ src/surf/LinkImplIntf.hpp | 58 ++++++++ src/surf/SplitDuplexLinkImpl.cpp | 99 +++++++++++++ src/surf/SplitDuplexLinkImpl.hpp | 81 +++++++++++ src/surf/SplitDuplexLinkImpl_test.cpp | 75 ++++++++++ src/surf/network_cm02.cpp | 17 ++- src/surf/network_cm02.hpp | 2 +- src/surf/network_interface.cpp | 120 --------------- src/surf/network_interface.hpp | 64 +------- src/surf/network_ns3.cpp | 22 +-- src/surf/network_ns3.hpp | 8 +- src/surf/network_wifi.cpp | 3 +- src/surf/network_wifi.hpp | 2 +- src/surf/ptask_L07.cpp | 13 +- src/surf/ptask_L07.hpp | 2 +- src/surf/sg_platf.cpp | 71 +++++---- src/surf/xml/platf_private.hpp | 2 +- src/surf/xml/surfxml_sax_cb.cpp | 16 +- teshsuite/s4u/seal-platform/seal-platform.cpp | 4 +- teshsuite/simdag/flatifier/flatifier.tesh | 25 ++++ .../two_hosts_one_link_splitduplex.xml | 5 +- tools/cmake/DefinePackages.cmake | 5 + tools/cmake/Tests.cmake | 1 + 59 files changed, 1023 insertions(+), 400 deletions(-) create mode 100644 src/surf/LinkImpl.cpp create mode 100644 src/surf/LinkImpl.hpp create mode 100644 src/surf/LinkImplIntf.hpp create mode 100644 src/surf/SplitDuplexLinkImpl.cpp create mode 100644 src/surf/SplitDuplexLinkImpl.hpp create mode 100644 src/surf/SplitDuplexLinkImpl_test.cpp diff --git a/MANIFEST.in b/MANIFEST.in index 3245396995..7296054e95 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2590,6 +2590,12 @@ include src/smpi/smpirun.in include src/smpi/smpitools.sh include src/surf/HostImpl.cpp include src/surf/HostImpl.hpp +include src/surf/LinkImpl.cpp +include src/surf/LinkImpl.hpp +include src/surf/LinkImplIntf.hpp +include src/surf/SplitDuplexLinkImpl.cpp +include src/surf/SplitDuplexLinkImpl.hpp +include src/surf/SplitDuplexLinkImpl_test.cpp include src/surf/cpu_cas01.cpp include src/surf/cpu_cas01.hpp include src/surf/cpu_interface.cpp diff --git a/docs/source/Platform_cpp.rst b/docs/source/Platform_cpp.rst index cbbd33bbf3..f3022b91a0 100644 --- a/docs/source/Platform_cpp.rst +++ b/docs/source/Platform_cpp.rst @@ -65,15 +65,19 @@ under the hood, SimGrid creates 2 links in this case: the *1_UP* link and the *1_DOWN* link. As you can see, the selection of link to use in the tag is done by the ``direction=`` parameter. -Using the C++ interface, you should describe both links separately and use them -in the route description. +Using the C++ interface, you can use the specific function to create these 2 links. Note +that you need to define the direction in the add_route function when adding a route containing +a split-duplex link. Otherwise, SimGrid cannot know which link (UP/DOWN) to use. .. code-block:: cpp - Link* l_up = zone->create_link("1_UP", "125MBps")->set_latency("24us")->seal(); - Link* l_down = zone->create_link("1_DOWN", "125MBps")->set_latency("24us")->seal(); + auto* link = zone->create_split_duplex_link("1", "125MBps")->set_latency("24us")->seal(); - zone->add_route(S1, C1, nullptr, nullptr, {link_down}); + zone->add_route(S1, C1, nullptr, nullptr, {{link, LinkInRoute::Direction::UP}}); + +.. note:: + Do not use set_sharing_policy(SharingPolicy::SPLITDUPLEX). + SimGrid will complain since set_sharing_policy should be used only with (SHARED and FATPIPE) Loading the platform diff --git a/examples/cpp/clusters-multicpu/s4u-clusters-multicpu.cpp b/examples/cpp/clusters-multicpu/s4u-clusters-multicpu.cpp index 88f6053584..9feae83fb5 100644 --- a/examples/cpp/clusters-multicpu/s4u-clusters-multicpu.cpp +++ b/examples/cpp/clusters-multicpu/s4u-clusters-multicpu.cpp @@ -110,13 +110,12 @@ create_hostzone(const sg4::NetZone* zone, const std::vector& /*coo /* the first CPU is the gateway */ if (i == 0) gateway = host; - /* create 2 links for a full-duplex communication */ - 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, std::vector{link_up}, false); - /* link DOWN, connection from outer to CPU */ - host_zone->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{link_down}, false); + /* create split-duplex link */ + sg4::SplitDuplexLink* link = host_zone->create_split_duplex_link("link-" + cpu_name, link_bw); + link->set_latency(link_lat)->seal(); + /* connecting CPU to outer world */ + host_zone->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, + std::vector{{link, sg4::LinkInRoute::Direction::UP}}, true); } /* seal newly created netzone */ host_zone->seal(); diff --git a/examples/cpp/comm-serialize/s4u-comm-serialize.cpp b/examples/cpp/comm-serialize/s4u-comm-serialize.cpp index 6afc5544b0..81a52d9da5 100644 --- a/examples/cpp/comm-serialize/s4u-comm-serialize.cpp +++ b/examples/cpp/comm-serialize/s4u-comm-serialize.cpp @@ -104,14 +104,11 @@ int main(int argc, char* argv[]) auto* receiver = zone->create_host("receiver", 1)->seal(); /* create split-duplex link1 (UP/DOWN), limiting the number of concurrent flows in it for 2 */ - auto* link_up = zone->create_link("link1_up", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal(); - auto* link_down = zone->create_link("link1_down", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal(); + auto* link = zone->create_split_duplex_link("link1", 10e9)->set_latency(10e-6)->set_concurrency_limit(2)->seal(); /* create routes between nodes */ - zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr, std::vector{link_up}, - false); - zone->add_route(receiver->get_netpoint(), sender->get_netpoint(), nullptr, nullptr, - std::vector{link_down}, false); + zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr, + std::vector{{link, sg4::LinkInRoute::Direction::UP}}, true); zone->seal(); /* create actors Sender/Receiver */ diff --git a/examples/cpp/network-factors/s4u-network-factors.cpp b/examples/cpp/network-factors/s4u-network-factors.cpp index 0e2d09d536..60018a1d9f 100644 --- a/examples/cpp/network-factors/s4u-network-factors.cpp +++ b/examples/cpp/network-factors/s4u-network-factors.cpp @@ -75,15 +75,15 @@ static void load_platform() /* create host */ const sg4::Host* host = root->create_host(hostname, 1)->set_core_count(32)->seal(); /* create UP/DOWN link */ - sg4::Link* l_up = root->create_link(hostname + "_up", BW_REMOTE)->set_latency(LATENCY)->seal(); - sg4::Link* l_down = root->create_link(hostname + "_down", BW_REMOTE)->set_latency(LATENCY)->seal(); + sg4::Link* l = root->create_split_duplex_link(hostname, BW_REMOTE)->set_latency(LATENCY)->seal(); /* add link UP/DOWN for communications from the host */ - root->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector{l_up}, false); - root->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{l_down}, false); + root->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, + std::vector{{l, sg4::LinkInRoute::Direction::UP}}, true); sg4::Link* loopback = root->create_link(hostname + "_loopback", BW_LOCAL)->set_latency(LATENCY)->seal(); - root->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, std::vector{loopback}); + root->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, + std::vector{loopback}); } root->seal(); diff --git a/examples/cpp/plugin-prodcons/s4u-plugin-prodcons.cpp b/examples/cpp/plugin-prodcons/s4u-plugin-prodcons.cpp index 67c2659bea..d9eb7d888b 100644 --- a/examples/cpp/plugin-prodcons/s4u-plugin-prodcons.cpp +++ b/examples/cpp/plugin-prodcons/s4u-plugin-prodcons.cpp @@ -63,11 +63,10 @@ int main(int argc, char* argv[]) const auto* host = cluster->create_host(hostname, "1Gf"); std::string linkname = std::string("cluster") + "_link_" + std::to_string(i); - auto* link_up = cluster->create_link(linkname + "_UP", "1Gbps"); - auto* link_down = cluster->create_link(linkname + "_DOWN", "1Gbps"); + auto* link = cluster->create_split_duplex_link(linkname, "1Gbps"); - cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector{link_up}, false); - cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{link_down}, false); + cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, + std::vector{{link, sg4::LinkInRoute::Direction::UP}}, true); } auto* router = cluster->create_router("cluster_router"); diff --git a/examples/platforms/griffon.cpp b/examples/platforms/griffon.cpp index d326305dd1..3b9207a7d2 100644 --- a/examples/platforms/griffon.cpp +++ b/examples/platforms/griffon.cpp @@ -35,13 +35,11 @@ create_cabinet(const sg4::NetZone* root, const std::string& name, const std::vec /* create host */ const sg4::Host* host = cluster->create_host(hostname, "286.087kf"); /* create UP/DOWN link */ - sg4::Link* l_up = cluster->create_link(hostname + "_up", "125MBps")->set_latency("24us")->seal(); - sg4::Link* l_down = cluster->create_link(hostname + "_down", "125MBps")->set_latency("24us")->seal(); + auto* link = cluster->create_split_duplex_link(hostname, "125MBps")->set_latency("24us")->seal(); - /* add link UP and backbone for communications from the host */ - cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector{l_up, l_bb}, false); - /* add backbone and link DOWN for communications to the host */ - cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{l_bb, l_down}, false); + /* add link and backbone for communications from the host */ + cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, + std::vector{{link, sg4::LinkInRoute::Direction::UP}, l_bb}, true); } /* create router */ diff --git a/examples/platforms/routing_cluster.cpp b/examples/platforms/routing_cluster.cpp index eb97e964ae..0f150b1937 100644 --- a/examples/platforms/routing_cluster.cpp +++ b/examples/platforms/routing_cluster.cpp @@ -39,9 +39,11 @@ static void create_cluster(const sg4::NetZone* root, const std::string& cluster_ } /* add link UP and backbone for communications from the host */ - cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector{l_up, l_bb}, false); + cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector{l_up, l_bb}, + false); /* add backbone and link DOWN for communications to the host */ - cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{l_bb, l_down}, false); + cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector{l_bb, l_down}, + false); } /* create router */ diff --git a/include/simgrid/forward.h b/include/simgrid/forward.h index 32a23f4fa6..bbfbd1c756 100644 --- a/include/simgrid/forward.h +++ b/include/simgrid/forward.h @@ -66,6 +66,7 @@ XBT_PUBLIC void intrusive_ptr_release(Io* i); XBT_PUBLIC void intrusive_ptr_add_ref(Io* i); class Link; +class SplitDuplexLink; class Mailbox; @@ -163,6 +164,8 @@ class CpuModel; class NetworkModel; class NetworkModelIntf; class LinkImpl; +class SplitDuplexLinkImpl; +class LinkImplIntf; class NetworkAction; class DiskImpl; class DiskModel; diff --git a/include/simgrid/kernel/routing/DijkstraZone.hpp b/include/simgrid/kernel/routing/DijkstraZone.hpp index 66e41647bc..98af529eea 100644 --- a/include/simgrid/kernel/routing/DijkstraZone.hpp +++ b/include/simgrid/kernel/routing/DijkstraZone.hpp @@ -51,7 +51,7 @@ public: */ void get_local_route(const NetPoint* src, const NetPoint* dst, Route* route, double* lat) override; void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) override; + const std::vector& link_list, bool symmetrical) override; }; } // namespace routing } // namespace kernel diff --git a/include/simgrid/kernel/routing/FloydZone.hpp b/include/simgrid/kernel/routing/FloydZone.hpp index 0277648957..83539d1b00 100644 --- a/include/simgrid/kernel/routing/FloydZone.hpp +++ b/include/simgrid/kernel/routing/FloydZone.hpp @@ -37,7 +37,7 @@ public: void get_local_route(const NetPoint* src, const NetPoint* dst, Route* into, double* latency) override; void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) override; + const std::vector& link_list, bool symmetrical) override; }; } // namespace routing } // namespace kernel diff --git a/include/simgrid/kernel/routing/FullZone.hpp b/include/simgrid/kernel/routing/FullZone.hpp index df8a1896f0..35a937709f 100644 --- a/include/simgrid/kernel/routing/FullZone.hpp +++ b/include/simgrid/kernel/routing/FullZone.hpp @@ -31,7 +31,7 @@ public: void get_local_route(const NetPoint* src, const NetPoint* dst, Route* into, double* latency) override; void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) override; + const std::vector& link_list, bool symmetrical) override; }; } // namespace routing } // namespace kernel diff --git a/include/simgrid/kernel/routing/NetZoneImpl.hpp b/include/simgrid/kernel/routing/NetZoneImpl.hpp index 430a1671ed..f81e9481d0 100644 --- a/include/simgrid/kernel/routing/NetZoneImpl.hpp +++ b/include/simgrid/kernel/routing/NetZoneImpl.hpp @@ -110,6 +110,10 @@ protected: /** @brief Get the NetZone that is represented by the netpoint */ const NetZoneImpl* get_netzone_recursive(const NetPoint* netpoint) const; + /** @brief Get the list of LinkImpl* to add in a route, considering split-duplex links and the direction */ + std::vector get_link_list_impl(const std::vector& link_list, + bool backroute) const; + public: enum class RoutingMode { base, /**< Base case: use simple link lists for routing */ @@ -156,11 +160,12 @@ public: s4u::Disk* create_disk(const std::string& name, double read_bandwidth, double write_bandwidth); /** @brief Make a link within that NetZone */ virtual s4u::Link* create_link(const std::string& name, const std::vector& bandwidths); + s4u::SplitDuplexLink* create_split_duplex_link(const std::string& name, const std::vector& bandwidths); /** @brief Make a router within that NetZone */ NetPoint* create_router(const std::string& name); /** @brief Creates a new route in this NetZone */ virtual void add_bypass_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - std::vector& link_list, bool symmetrical); + const std::vector& link_list); /** @brief Seal your netzone once you're done adding content, and before routing stuff through it */ void seal(); @@ -169,7 +174,7 @@ public: virtual int add_component(kernel::routing::NetPoint* elm); /* A host, a router or a netzone, whatever */ virtual void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical); + const std::vector& link_list, bool symmetrical); /** @brief Set parent of this Netzone */ void set_parent(NetZoneImpl* parent); /** @brief Set network model for this Netzone */ @@ -197,6 +202,13 @@ public: virtual void get_graph(const s_xbt_graph_t* graph, std::map>* nodes, std::map>* edges) = 0; + /*** Called on each newly created regular route (not on bypass routes) */ + static xbt::signal const& link_list)> + on_route_creation; // XBT_ATTRIB_DEPRECATED_v332 : should be an internal signal used by NS3.. if necessary, + // callback shouldn't use LinkImpl* + private: RoutingMode hierarchy_ = RoutingMode::base; std::shared_ptr network_model_; diff --git a/include/simgrid/kernel/routing/RoutedZone.hpp b/include/simgrid/kernel/routing/RoutedZone.hpp index 7fcd038088..08e5c13801 100644 --- a/include/simgrid/kernel/routing/RoutedZone.hpp +++ b/include/simgrid/kernel/routing/RoutedZone.hpp @@ -66,7 +66,7 @@ protected: } void get_route_check_params(const NetPoint* src, const NetPoint* dst) const; void add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) const; + const std::vector& link_list, bool symmetrical) const; }; } // namespace routing } // namespace kernel diff --git a/include/simgrid/kernel/routing/StarZone.hpp b/include/simgrid/kernel/routing/StarZone.hpp index 4f647d7df9..2b030c5da6 100644 --- a/include/simgrid/kernel/routing/StarZone.hpp +++ b/include/simgrid/kernel/routing/StarZone.hpp @@ -69,7 +69,7 @@ public: std::map>* edges) override; void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) override; + const std::vector& link_list, bool symmetrical) override; void do_seal() override; private: diff --git a/include/simgrid/s4u/Engine.hpp b/include/simgrid/s4u/Engine.hpp index 7f43c2fe35..074a242bc5 100644 --- a/include/simgrid/s4u/Engine.hpp +++ b/include/simgrid/s4u/Engine.hpp @@ -121,6 +121,11 @@ public: std::vector get_all_links() const; std::vector get_filtered_links(const std::function& filter) const; Link* link_by_name(const std::string& name) const; + /** + * @brief Find a split-duplex link from its name. + * @throw std::invalid_argument if the searched link does not exist. + */ + SplitDuplexLink* split_duplex_link_by_name(const std::string& name) const; Link* link_by_name_or_null(const std::string& name) const; Mailbox* mailbox_by_name_or_create(const std::string& name) const; diff --git a/include/simgrid/s4u/Link.hpp b/include/simgrid/s4u/Link.hpp index b00085377c..1ab58c8a78 100644 --- a/include/simgrid/s4u/Link.hpp +++ b/include/simgrid/s4u/Link.hpp @@ -34,16 +34,17 @@ class XBT_PUBLIC Link : public xbt::Extendable { friend kernel::resource::LinkImpl; #endif +protected: // Links are created from the NetZone, and destroyed by their private implementation when the simulation ends - explicit Link(kernel::resource::LinkImpl* pimpl) : pimpl_(pimpl) {} + explicit Link(kernel::resource::LinkImplIntf* pimpl) : pimpl_(pimpl) {} virtual ~Link() = default; - // The private implementation, that never changes - kernel::resource::LinkImpl* const pimpl_; + // The implementation that never changes + kernel::resource::LinkImplIntf* const pimpl_; public: enum class SharingPolicy { WIFI = 3, SPLITDUPLEX = 2, SHARED = 1, FATPIPE = 0 }; - kernel::resource::LinkImpl* get_impl() const { return pimpl_; } + kernel::resource::LinkImpl* get_impl() const; /** @brief Retrieve a link from its name */ static Link* by_name(const std::string& name); @@ -149,6 +150,54 @@ public: static xbt::signal on_communication_state_change; }; + +/** + * @beginrst + * A SplitDuplexLink encapsulates the :cpp:class:`links ` which + * compose a Split-Duplex link. Remember that a Split-Duplex link is nothing more than + * a pair of up/down links. + * @endrst + */ +class XBT_PUBLIC SplitDuplexLink : public Link { +public: + explicit SplitDuplexLink(kernel::resource::LinkImplIntf* pimpl) : Link(pimpl) {} + /** @brief Get the link direction up*/ + Link* get_link_up() const; + /** @brief Get the link direction down */ + Link* get_link_down() const; + + /** @brief Retrieve a link from its name */ + static SplitDuplexLink* by_name(const std::string& name); +}; + +/** + * @beginrst + * Another encapsulation for using links in the :cpp:function:: NetZone::add_route + * + * When adding a route with split-duplex links, you need to specify the direction of the link + * so SimGrid can know exactly which physical link to insert in the route. + * + * For shared/fat-pipe links, use the Direction::NONE since they don't have + * the concept of UP/DOWN links. + * @endrst + */ +class XBT_PUBLIC LinkInRoute { +public: + enum class Direction { UP = 2, DOWN = 1, NONE = 0 }; + + LinkInRoute(const Link* link) : link_(link) {} + LinkInRoute(const Link* link, Direction d) : link_(link), direction_(d) {} + + /** @brief Get direction of this link in the route: UP or DOWN */ + Direction get_direction() const { return direction_; } + /** @brief Get pointer to the link */ + const Link* get_link() const { return link_; } + +private: + const Link* link_; + Direction direction_ = Direction::NONE; +}; + } // namespace s4u } // namespace simgrid diff --git a/include/simgrid/s4u/NetZone.hpp b/include/simgrid/s4u/NetZone.hpp index ed6afa8d3c..bd4cc7b2ff 100644 --- a/include/simgrid/s4u/NetZone.hpp +++ b/include/simgrid/s4u/NetZone.hpp @@ -80,26 +80,42 @@ public: * @param dst Destination netzone' netpoint * @param gw_src Netpoint of the gateway in the source netzone * @param gw_dst Netpoint of the gateway in the destination netzone - * @param link_list List of links used in this communication + * @param link_list List of links and their direction used in this communication * @param symmetrical Bi-directional communication */ void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, - kernel::routing::NetPoint* gw_dst, const std::vector& link_list, bool symmetrical = true); + kernel::routing::NetPoint* gw_dst, const std::vector& link_list, bool symmetrical = true); + + XBT_ATTRIB_DEPRECATED_v332("Please use add_route() method which uses s4u::LinkInRoute instead of " + "LinkImpl") void add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, + kernel::routing::NetPoint* gw_src, + kernel::routing::NetPoint* gw_dst, + const std::vector& link_list, + bool symmetrical); + + XBT_ATTRIB_DEPRECATED_v332("Please use add_bypass_route() method which uses s4u::LinkInRoute instead of " + "LinkImpl") void add_bypass_route(kernel::routing::NetPoint* src, + kernel::routing::NetPoint* dst, + kernel::routing::NetPoint* gw_src, + kernel::routing::NetPoint* gw_dst, + std::vector& link_list, + bool /*symmetrical*/); #ifndef DOXYGEN - XBT_ATTRIB_DEPRECATED_v332("Please use add_route() method which uses s4u::Link instead of LinkImpl") void add_route( - kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, - kernel::routing::NetPoint* gw_dst, const std::vector& link_list, bool symmetrical); #endif void add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, - std::vector& link_list, bool symmetrical); + const std::vector& link_list); +#ifndef DOXYGEN /*** Called on each newly created regular route (not on bypass routes) */ static xbt::signal const& link_list)> - on_route_creation; + on_route_creation; // XBT_ATTRIB_DEPRECATED_v332 : should not be used by users, used by ns3.. if necessary, + // signal shouldn't use LinkImpl* +#endif + static xbt::signal on_creation; static xbt::signal on_seal; @@ -133,6 +149,22 @@ public: s4u::Link* create_link(const std::string& name, const std::vector& bandwidths); s4u::Link* create_link(const std::string& name, const std::string& bandwidth); + /** + * @brief Create a split-duplex link + * + * In SimGrid, split-duplex links are a composition of 2 regular (shared) links (up/down). + * + * This function eases its utilization by creating the 2 links for you. We append a suffix + * "_UP" and "_DOWN" to your link name to identify each of them. + * + * Both up/down links have exactly the same bandwidth + * + * @param name Name of the link + * @param bandwidth Speed + */ + s4u::SplitDuplexLink* create_split_duplex_link(const std::string& name, const std::string& bandwidth); + s4u::SplitDuplexLink* create_split_duplex_link(const std::string& name, double bandwidth); + kernel::resource::NetworkModelIntf* get_network_model() const; /** @@ -146,8 +178,8 @@ public: NetZone* seal(); private: - /** @brief Auxiliary function to get list of LinkImpl */ - static std::vector get_link_list_impl(const std::vector& link_list); + /** @brief Auxiliary function to convert types */ + static std::vector convert_to_linkInRoute(const std::vector& link_list); }; // External constructors so that the types (and the types of their content) remain hidden diff --git a/src/bindings/lua/lua_platf.cpp b/src/bindings/lua/lua_platf.cpp index 56eb196c5c..f7edcdb04e 100644 --- a/src/bindings/lua/lua_platf.cpp +++ b/src/bindings/lua/lua_platf.cpp @@ -347,13 +347,13 @@ int console_add_route(lua_State *L) { boost::split(names, str, boost::is_any_of(", \t\r\n")); if (names.empty()) { /* unique name */ - route.link_list.push_back(simgrid::s4u::Link::by_name(lua_tostring(L, -1))->get_impl()); + route.link_list.emplace_back(simgrid::s4u::LinkInRoute(simgrid::s4u::Link::by_name(lua_tostring(L, -1)))); } else { // Several names separated by , \t\r\n for (auto const& name : names) { if (name.length() > 0) { - simgrid::kernel::resource::LinkImpl* link = simgrid::s4u::Link::by_name(name)->get_impl(); - route.link_list.push_back(link); + simgrid::s4u::LinkInRoute link(simgrid::s4u::Link::by_name(name)); + route.link_list.emplace_back(link); } } } @@ -413,13 +413,13 @@ int console_add_ASroute(lua_State *L) { boost::split(names, str, boost::is_any_of(", \t\r\n")); if (names.empty()) { /* unique name with no comma */ - ASroute.link_list.push_back(simgrid::s4u::Link::by_name(lua_tostring(L, -1))->get_impl()); + ASroute.link_list.emplace_back(simgrid::s4u::LinkInRoute(simgrid::s4u::Link::by_name(lua_tostring(L, -1)))); } else { // Several names separated by , \t\r\n for (auto const& name : names) { if (name.length() > 0) { - simgrid::kernel::resource::LinkImpl* link = simgrid::s4u::Link::by_name(name)->get_impl(); - ASroute.link_list.push_back(link); + simgrid::s4u::LinkInRoute link(simgrid::s4u::Link::by_name(name)); + ASroute.link_list.emplace_back(link); } } } diff --git a/src/kernel/EngineImpl.cpp b/src/kernel/EngineImpl.cpp index 2ff94abc34..fecdfb99eb 100644 --- a/src/kernel/EngineImpl.cpp +++ b/src/kernel/EngineImpl.cpp @@ -123,6 +123,11 @@ void EngineImpl::add_model(std::shared_ptr model, const std::ve models_prio_[model_name] = std::move(model); } +void EngineImpl::add_split_duplex_link(const std::string& name, std::unique_ptr link) +{ + split_duplex_links_[name] = std::move(link); +} + /** Wake up all actors waiting for a Surf action to finish */ void EngineImpl::wake_all_waiting_actors() const { diff --git a/src/kernel/EngineImpl.hpp b/src/kernel/EngineImpl.hpp index db00760543..79fa6568ea 100644 --- a/src/kernel/EngineImpl.hpp +++ b/src/kernel/EngineImpl.hpp @@ -19,6 +19,7 @@ #include "src/kernel/activity/SleepImpl.hpp" #include "src/kernel/activity/SynchroRaw.hpp" #include "src/kernel/actor/ActorImpl.hpp" +#include "src/surf/SplitDuplexLinkImpl.hpp" #include #include @@ -34,6 +35,9 @@ namespace kernel { class EngineImpl { std::map> hosts_; std::map> links_; + /* save split-duplex links separately, keep links_ with only LinkImpl* seen by the user + * members of a split-duplex are saved in the links_ */ + std::map> split_duplex_links_; std::unordered_map netpoints_; std::unordered_map mailboxes_; @@ -117,6 +121,7 @@ public: actor::ActorImpl* get_actor_by_pid(aid_t pid); void add_actor(aid_t pid, actor::ActorImpl* actor) { actor_list_[pid] = actor; } void remove_actor(aid_t pid) { actor_list_.erase(pid); } + void add_split_duplex_link(const std::string& name, std::unique_ptr link); #if SIMGRID_HAVE_MC xbt_dynar_t get_actors_vector() const { return actors_vector_; } diff --git a/src/kernel/routing/DijkstraZone.cpp b/src/kernel/routing/DijkstraZone.cpp index bb224b6b0e..e7b9d2c25d 100644 --- a/src/kernel/routing/DijkstraZone.cpp +++ b/src/kernel/routing/DijkstraZone.cpp @@ -206,14 +206,16 @@ void DijkstraZone::get_local_route(const NetPoint* src, const NetPoint* dst, Rou } void DijkstraZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list_, bool symmetrical) + const std::vector& link_list, bool symmetrical) { - add_route_check_params(src, dst, gw_src, gw_dst, link_list_, symmetrical); + add_route_check_params(src, dst, gw_src, gw_dst, link_list, symmetrical); - new_edge(src->id(), dst->id(), new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, true)); + new_edge(src->id(), dst->id(), + new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, false), true)); if (symmetrical) - new_edge(dst->id(), src->id(), new_extended_route(get_hierarchy(), gw_dst, gw_src, link_list_, false)); + new_edge(dst->id(), src->id(), + new_extended_route(get_hierarchy(), gw_dst, gw_src, get_link_list_impl(link_list, true), false)); } void DijkstraZone::new_edge(int src_id, int dst_id, Route* route) diff --git a/src/kernel/routing/DijkstraZone_test.cpp b/src/kernel/routing/DijkstraZone_test.cpp index 9689c18368..d222e968d5 100644 --- a/src/kernel/routing/DijkstraZone_test.cpp +++ b/src/kernel/routing/DijkstraZone_test.cpp @@ -31,6 +31,6 @@ TEST_CASE("kernel::routing::DijkstraZone: mix new routes and hosts", "") 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{link}, true)); + std::vector{link}, true)); } } diff --git a/src/kernel/routing/FloydZone.cpp b/src/kernel/routing/FloydZone.cpp index e48a460856..6674f5bbbf 100644 --- a/src/kernel/routing/FloydZone.cpp +++ b/src/kernel/routing/FloydZone.cpp @@ -69,13 +69,13 @@ void FloydZone::get_local_route(const NetPoint* src, const NetPoint* dst, Route* } void FloydZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list_, bool symmetrical) + const std::vector& link_list, bool symmetrical) { /* set the size of table routing */ unsigned int table_size = get_table_size(); init_tables(table_size); - add_route_check_params(src, dst, gw_src, gw_dst, link_list_, symmetrical); + add_route_check_params(src, dst, gw_src, gw_dst, link_list, symmetrical); /* Check that the route does not already exist */ if (gw_dst && gw_src) // netzone route (to adapt the error message, if any) @@ -87,8 +87,8 @@ void FloydZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoi "The route between %s and %s already exists (Rq: routes are symmetrical by default).", src->get_cname(), dst->get_cname()); - link_table_[src->id()][dst->id()] = - std::unique_ptr(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, true)); + link_table_[src->id()][dst->id()] = std::unique_ptr( + new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, false), true)); predecessor_table_[src->id()][dst->id()] = src->id(); cost_table_[src->id()][dst->id()] = link_table_[src->id()][dst->id()]->link_list_.size(); @@ -115,8 +115,8 @@ void FloydZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoi XBT_DEBUG("Load NetzoneRoute from \"%s(%s)\" to \"%s(%s)\"", dst->get_cname(), gw_src->get_cname(), src->get_cname(), gw_dst->get_cname()); - link_table_[dst->id()][src->id()] = - std::unique_ptr(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, false)); + link_table_[dst->id()][src->id()] = std::unique_ptr( + new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, true), 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 */ diff --git a/src/kernel/routing/FloydZone_test.cpp b/src/kernel/routing/FloydZone_test.cpp index 7727d39dc1..d47351cc7f 100644 --- a/src/kernel/routing/FloydZone_test.cpp +++ b/src/kernel/routing/FloydZone_test.cpp @@ -30,6 +30,6 @@ TEST_CASE("kernel::routing::FloydZone: mix new routes and hosts", "") 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{link}, true)); + std::vector{link}, true)); } } diff --git a/src/kernel/routing/FullZone.cpp b/src/kernel/routing/FullZone.cpp index 9dc19a1e27..dcbf949906 100644 --- a/src/kernel/routing/FullZone.cpp +++ b/src/kernel/routing/FullZone.cpp @@ -55,7 +55,7 @@ void FullZone::get_local_route(const NetPoint* src, const NetPoint* dst, Route* } void FullZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) + const std::vector& link_list, bool symmetrical) { add_route_check_params(src, dst, gw_src, gw_dst, link_list, symmetrical); @@ -72,8 +72,8 @@ void FullZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoin dst->get_cname()); /* Add the route to the base */ - routing_table_[src->id()][dst->id()] = - std::unique_ptr(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, true)); + routing_table_[src->id()][dst->id()] = std::unique_ptr( + new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, false), true)); if (symmetrical && src != dst) { if (gw_dst && gw_src) { @@ -91,8 +91,8 @@ void FullZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoin "The route between %s and %s already exists. You should not declare the reverse path as symmetrical.", dst->get_cname(), src->get_cname()); - routing_table_[dst->id()][src->id()] = - std::unique_ptr(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, false)); + routing_table_[dst->id()][src->id()] = std::unique_ptr( + new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, true), false)); } } } // namespace routing diff --git a/src/kernel/routing/FullZone_test.cpp b/src/kernel/routing/FullZone_test.cpp index f630fdc32f..f67e156c10 100644 --- a/src/kernel/routing/FullZone_test.cpp +++ b/src/kernel/routing/FullZone_test.cpp @@ -30,6 +30,6 @@ TEST_CASE("kernel::routing::FullZone: mix new routes and hosts", "[bug]") 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{link}, true)); + std::vector{link}, true)); } } diff --git a/src/kernel/routing/NetZoneImpl.cpp b/src/kernel/routing/NetZoneImpl.cpp index d5dc99f508..d357d6af6c 100644 --- a/src/kernel/routing/NetZoneImpl.cpp +++ b/src/kernel/routing/NetZoneImpl.cpp @@ -11,6 +11,7 @@ #include "src/kernel/EngineImpl.hpp" #include "src/kernel/resource/DiskImpl.hpp" #include "src/surf/HostImpl.hpp" +#include "src/surf/SplitDuplexLinkImpl.hpp" #include "src/surf/cpu_interface.hpp" #include "src/surf/network_interface.hpp" #include "surf/surf.hpp" @@ -64,6 +65,11 @@ static void surf_config_models_setup() disk_model->model_init_preparse(); } +xbt::signal const& link_list)> + NetZoneImpl::on_route_creation; + NetZoneImpl::NetZoneImpl(const std::string& name) : piface_(this), name_(name) { /* workaroud: first netzoneImpl will be the root netzone. @@ -161,6 +167,17 @@ s4u::Link* NetZoneImpl::create_link(const std::string& name, const std::vectorcreate_link(name, bandwidths)->get_iface(); } +s4u::SplitDuplexLink* NetZoneImpl::create_split_duplex_link(const std::string& name, + const std::vector& bandwidths) +{ + auto* link_up = network_model_->create_link(name + "_UP", bandwidths); + auto* link_down = network_model_->create_link(name + "_DOWN", bandwidths); + auto link = std::make_unique(name, link_up, link_down); + auto* link_iface = link->get_iface(); + EngineImpl::get_instance()->add_split_duplex_link(name, std::move(link)); + return link_iface; +} + s4u::Disk* NetZoneImpl::create_disk(const std::string& name, double read_bandwidth, double write_bandwidth) { xbt_assert(disk_model_, @@ -184,27 +201,64 @@ int NetZoneImpl::add_component(NetPoint* elm) return vertices_.size() - 1; // The rank of the newly created object } +std::vector NetZoneImpl::get_link_list_impl(const std::vector& link_list, + bool backroute) const +{ + std::vector links; + + for (const auto& link : link_list) { + resource::LinkImpl* link_impl; + if (link.get_link()->get_sharing_policy() == s4u::Link::SharingPolicy::SPLITDUPLEX) { + const auto* sd_link = dynamic_cast(link.get_link()); + xbt_assert(sd_link, + "Add_route: cast to SpliDuplexLink impossible. This should not happen, please contact SimGrid team"); + switch (link.get_direction()) { + case s4u::LinkInRoute::Direction::UP: + if (backroute) + link_impl = sd_link->get_link_down()->get_impl(); + else + link_impl = sd_link->get_link_up()->get_impl(); + break; + case s4u::LinkInRoute::Direction::DOWN: + if (backroute) + link_impl = sd_link->get_link_up()->get_impl(); + else + link_impl = sd_link->get_link_down()->get_impl(); + break; + case s4u::LinkInRoute::Direction::NONE: + default: + throw std::invalid_argument("Invalid add_route. Split-Duplex link without a direction: " + + link.get_link()->get_name()); + } + } else { + link_impl = link.get_link()->get_impl(); + } + links.push_back(link_impl); + } + return links; +} + void NetZoneImpl::add_route(NetPoint* /*src*/, NetPoint* /*dst*/, NetPoint* /*gw_src*/, NetPoint* /*gw_dst*/, - const std::vector& /*link_list_*/, bool /*symmetrical*/) + const std::vector& /*link_list_*/, bool /*symmetrical*/) { xbt_die("NetZone '%s' does not accept new routes (wrong class).", get_cname()); } void NetZoneImpl::add_bypass_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - std::vector& link_list_, bool /* symmetrical */) + const std::vector& link_list) { /* Argument validity checks */ if (gw_dst) { XBT_DEBUG("Load bypassNetzoneRoute from %s@%s to %s@%s", src->get_cname(), gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname()); - xbt_assert(not link_list_.empty(), "Bypass route between %s@%s and %s@%s cannot be empty.", src->get_cname(), + xbt_assert(not link_list.empty(), "Bypass route between %s@%s and %s@%s cannot be empty.", src->get_cname(), gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname()); xbt_assert(bypass_routes_.find({src, dst}) == bypass_routes_.end(), "The bypass route between %s@%s and %s@%s already exists.", src->get_cname(), gw_src->get_cname(), dst->get_cname(), gw_dst->get_cname()); } else { XBT_DEBUG("Load bypassRoute from %s to %s", src->get_cname(), dst->get_cname()); - xbt_assert(not link_list_.empty(), "Bypass route between %s and %s cannot be empty.", src->get_cname(), + xbt_assert(not link_list.empty(), "Bypass route between %s and %s cannot be empty.", src->get_cname(), dst->get_cname()); xbt_assert(bypass_routes_.find({src, dst}) == bypass_routes_.end(), "The bypass route between %s and %s already exists.", src->get_cname(), dst->get_cname()); @@ -212,7 +266,8 @@ void NetZoneImpl::add_bypass_route(NetPoint* src, NetPoint* dst, NetPoint* gw_sr /* Build a copy that will be stored in the dict */ auto* newRoute = new BypassRoute(gw_src, gw_dst); - newRoute->links.insert(newRoute->links.end(), begin(link_list_), end(link_list_)); + auto converted_list = get_link_list_impl(link_list, false); + newRoute->links.insert(newRoute->links.end(), begin(converted_list), end(converted_list)); /* Store it */ bypass_routes_.insert({{src, dst}, newRoute}); diff --git a/src/kernel/routing/RoutedZone.cpp b/src/kernel/routing/RoutedZone.cpp index 3c28dcee41..7bbddf9848 100644 --- a/src/kernel/routing/RoutedZone.cpp +++ b/src/kernel/routing/RoutedZone.cpp @@ -149,7 +149,7 @@ void RoutedZone::get_route_check_params(const NetPoint* src, const NetPoint* dst src->get_cname(), dst->get_cname(), src_as->get_cname(), dst_as->get_cname(), get_cname()); } void RoutedZone::add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) const + const std::vector& link_list, bool symmetrical) const { const char* srcName = src->get_cname(); const char* dstName = dst->get_cname(); @@ -165,7 +165,8 @@ void RoutedZone::add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint* xbt_assert(not dst->is_netzone(), "When defining a route, dst cannot be a netzone such as '%s'. Did you meant to have a NetzoneRoute?", dstName); - s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, link_list); + s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, get_link_list_impl(link_list, false)); + NetZoneImpl::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, get_link_list_impl(link_list, false)); } else { XBT_DEBUG("Load NetzoneRoute from %s@%s to %s@%s", srcName, gw_src->get_cname(), dstName, gw_dst->get_cname()); xbt_assert(src->is_netzone(), "When defining a NetzoneRoute, src must be a netzone but '%s' is not", srcName); @@ -195,7 +196,8 @@ void RoutedZone::add_route_check_params(NetPoint* src, NetPoint* dst, NetPoint* "Invalid NetzoneRoute from %s@%s to %s@%s: gw_dst %s belongs to %s, not to %s.", srcName, gw_src->get_cname(), dstName, gw_dst->get_cname(), gw_dst->get_cname(), gw_dst->get_englobing_zone()->get_cname(), dst->get_cname()); - s4u::NetZone::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, link_list); + s4u::NetZone::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, get_link_list_impl(link_list, false)); + NetZoneImpl::on_route_creation(symmetrical, gw_src, gw_dst, gw_src, gw_dst, get_link_list_impl(link_list, false)); } } } // namespace routing diff --git a/src/kernel/routing/StarZone.cpp b/src/kernel/routing/StarZone.cpp index b91248d783..dad133fa9c 100644 --- a/src/kernel/routing/StarZone.cpp +++ b/src/kernel/routing/StarZone.cpp @@ -135,32 +135,31 @@ void StarZone::check_add_route_param(const NetPoint* src, const NetPoint* dst, c } void StarZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst, - const std::vector& link_list_, bool symmetrical) + const std::vector& link_list, bool symmetrical) { check_add_route_param(src, dst, gw_src, gw_dst, symmetrical); - s4u::NetZone::on_route_creation(symmetrical, src, dst, gw_src, gw_dst, link_list_); - /* loopback */ if (src == dst) { - routes_[src->id()].loopback = link_list_; + routes_[src->id()].loopback = get_link_list_impl(link_list, false); } else { /* src to everyone */ if (src) { auto& route = routes_[src->id()]; - route.links_up = link_list_; + route.links_up = get_link_list_impl(link_list, false); route.gateway = gw_src; route.links_up_set = true; if (symmetrical) { + auto links_down = get_link_list_impl(link_list, true); /* reverse it for down/symmetrical links */ - route.links_down.assign(link_list_.rbegin(), link_list_.rend()); + route.links_down.assign(links_down.rbegin(), links_down.rend()); route.links_down_set = true; } } /* dst to everyone */ if (dst) { auto& route = routes_[dst->id()]; - route.links_down = link_list_; + route.links_down = get_link_list_impl(link_list, false); route.gateway = gw_dst; route.links_down_set = true; } diff --git a/src/kernel/routing/StarZone_test.cpp b/src/kernel/routing/StarZone_test.cpp index d8d5206235..ef27bf5c3e 100644 --- a/src/kernel/routing/StarZone_test.cpp +++ b/src/kernel/routing/StarZone_test.cpp @@ -19,6 +19,21 @@ TEST_CASE("kernel::routing::StarZone: Creating Zone", "[creation]") REQUIRE(simgrid::s4u::create_star_zone("test")); } +TEST_CASE("kernel::routing::StarZone: Create links: exceptions", "") +{ + simgrid::s4u::Engine e("test"); + auto* zone = simgrid::s4u::create_star_zone("test"); + SECTION("create_link: invalid bandwidth") + { + REQUIRE_THROWS_AS(zone->create_link("link", "speed"), std::invalid_argument); + } + + SECTION("split-duplex create_link: invalid bandwidth") + { + REQUIRE_THROWS_AS(zone->create_split_duplex_link("link", "speed"), std::invalid_argument); + } +} + TEST_CASE("kernel::routing::StarZone: Adding routes (hosts): exception", "") { simgrid::s4u::Engine e("test"); @@ -95,10 +110,10 @@ TEST_CASE("kernel::routing::StarZone: Get routes: assert", "[.][assert]") const auto* host1 = zone->create_host("netpoint1", {100}); const auto* host2 = zone->create_host("netpoint2", {100}); - std::vector links; - links.push_back(zone->create_link("link1", {100})->get_impl()); - std::vector links2; - links2.push_back(zone->create_link("link2", {100})->get_impl()); + std::vector links; + links.emplace_back(zone->create_link("link1", {100})); + std::vector links2; + links2.emplace_back(zone->create_link("link2", {100})); SECTION("Get route: no UP link") { @@ -165,10 +180,10 @@ TEST_CASE("kernel::routing::StarZone: Get routes (hosts)", "") SECTION("Get route: no shared link") { - std::vector links; - links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl()); - std::vector links2; - links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl()); + std::vector links; + links.emplace_back(zone->create_link("link1", {100})->set_latency(10)); + std::vector links2; + links2.emplace_back(zone->create_link("link2", {200})->set_latency(20)); zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true); zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true); zone->seal(); @@ -186,13 +201,13 @@ TEST_CASE("kernel::routing::StarZone: Get routes (hosts)", "") SECTION("Get route: shared link(backbone)") { - auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl(); - std::vector links; - links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl()); - links.push_back(backbone); - std::vector links2; - links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl()); - links2.push_back(backbone); + auto* backbone = zone->create_link("backbone", {1000})->set_latency(100); + std::vector links; + links.emplace_back(zone->create_link("link1", {100})->set_latency(10)); + links.emplace_back(backbone); + std::vector links2; + links2.emplace_back(zone->create_link("link2", {200})->set_latency(20)); + links2.emplace_back(backbone); zone->add_route(host1->get_netpoint(), nullptr, nullptr, nullptr, links, true); zone->add_route(host2->get_netpoint(), nullptr, nullptr, nullptr, links2, true); @@ -210,10 +225,10 @@ TEST_CASE("kernel::routing::StarZone: Get routes (hosts)", "") SECTION("Get route: loopback") { - auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl(); - std::vector links; - links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl()); - links.push_back(backbone); + auto* backbone = zone->create_link("backbone", {1000})->set_latency(100); + std::vector links; + links.emplace_back(zone->create_link("link1", {100})->set_latency(10)); + links.emplace_back(backbone); zone->add_route(host1->get_netpoint(), host1->get_netpoint(), nullptr, nullptr, links, true); zone->seal(); @@ -243,10 +258,10 @@ TEST_CASE("kernel::routing::StarZone: Get routes (netzones)", "") SECTION("Get route: netzone") { - std::vector links; - links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl()); - std::vector links2; - links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl()); + std::vector links; + links.emplace_back(zone->create_link("link1", {100})->set_latency(10)); + std::vector links2; + links2.emplace_back(zone->create_link("link2", {200})->set_latency(20)); zone->add_route(subzone1->get_netpoint(), nullptr, router1, nullptr, links, true); zone->add_route(subzone2->get_netpoint(), nullptr, router2, nullptr, links2, true); zone->seal(); @@ -272,7 +287,7 @@ TEST_CASE("kernel::routing::StarZone: mix new routes and hosts", "") 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{link}, true)); + REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nullptr, nullptr, nullptr, + std::vector{link}, true)); } } diff --git a/src/kernel/routing/VivaldiZone.cpp b/src/kernel/routing/VivaldiZone.cpp index aa2a15d05a..8ac7639da8 100644 --- a/src/kernel/routing/VivaldiZone.cpp +++ b/src/kernel/routing/VivaldiZone.cpp @@ -66,8 +66,8 @@ void VivaldiZone::set_peer_link(NetPoint* netpoint, double bw_in, double bw_out) std::string link_down = "link_" + netpoint->get_name() + "_DOWN"; const auto* linkUp = create_link(link_up, std::vector{bw_out})->seal(); const auto* linkDown = create_link(link_down, std::vector{bw_in})->seal(); - add_route(netpoint, nullptr, nullptr, nullptr, {linkUp->get_impl()}, false); - add_route(nullptr, netpoint, nullptr, nullptr, {linkDown->get_impl()}, false); + add_route(netpoint, nullptr, nullptr, nullptr, std::vector{linkUp}, false); + add_route(nullptr, netpoint, nullptr, nullptr, std::vector{linkDown}, false); } void VivaldiZone::get_local_route(const NetPoint* src, const NetPoint* dst, Route* route, double* lat) diff --git a/src/s4u/s4u_Engine.cpp b/src/s4u/s4u_Engine.cpp index d70eb6ef39..47b512e668 100644 --- a/src/s4u/s4u_Engine.cpp +++ b/src/s4u/s4u_Engine.cpp @@ -236,6 +236,14 @@ Link* Engine::link_by_name(const std::string& name) const return link->second->get_iface(); } +SplitDuplexLink* Engine::split_duplex_link_by_name(const std::string& name) const +{ + auto link = pimpl->split_duplex_links_.find(name); + if (link == pimpl->split_duplex_links_.end()) + throw std::invalid_argument(std::string("Link not found: ") + name); + return link->second->get_iface(); +} + /** @brief Find a link from its name (or nullptr if that link does not exist) */ Link* Engine::link_by_name_or_null(const std::string& name) const { diff --git a/src/s4u/s4u_Link.cpp b/src/s4u/s4u_Link.cpp index 0f8886943e..65d544b48d 100644 --- a/src/s4u/s4u_Link.cpp +++ b/src/s4u/s4u_Link.cpp @@ -10,7 +10,7 @@ #include "simgrid/s4u/Link.hpp" #include "simgrid/sg_config.hpp" #include "simgrid/simix.hpp" -#include "src/kernel/lmm/maxmin.hpp" +#include "src/surf/SplitDuplexLinkImpl.hpp" #include "src/surf/network_interface.hpp" #include "src/surf/network_wifi.hpp" #include "xbt/log.h" @@ -35,6 +35,14 @@ Link* Link::by_name(const std::string& name) return Engine::get_instance()->link_by_name(name); } +kernel::resource::LinkImpl* Link::get_impl() const +{ + xbt_assert( + get_sharing_policy() != SharingPolicy::SPLITDUPLEX, + "Impossible to get a LinkImpl* from a Split-Duplex link. You should call this method to each UP/DOWN member"); + return dynamic_cast(pimpl_); +} + Link* Link::by_name_or_null(const std::string& name) { return Engine::get_instance()->link_by_name_or_null(name); @@ -96,7 +104,7 @@ Link* Link::set_sharing_policy(Link::SharingPolicy policy) { if (policy == SharingPolicy::SPLITDUPLEX) throw std::invalid_argument(std::string("Impossible to set split-duplex for the link: ") + get_name() + - std::string(". You should create a link-up and link-down to emulate this behavior")); + std::string(". Use NetZone::create_split_duplex_link.")); kernel::actor::simcall([this, policy] { pimpl_->set_sharing_policy(policy); }); return this; @@ -185,6 +193,21 @@ Link* Link::set_properties(const std::unordered_map& p return this; } +Link* SplitDuplexLink::get_link_up() const +{ + return dynamic_cast(pimpl_)->get_link_up(); +} + +Link* SplitDuplexLink::get_link_down() const +{ + return dynamic_cast(pimpl_)->get_link_down(); +} + +SplitDuplexLink* SplitDuplexLink::by_name(const std::string& name) +{ + return Engine::get_instance()->split_duplex_link_by_name(name); +} + } // namespace s4u } // namespace simgrid diff --git a/src/s4u/s4u_Netzone.cpp b/src/s4u/s4u_Netzone.cpp index d9d23ef6a3..428c19fef7 100644 --- a/src/s4u/s4u_Netzone.cpp +++ b/src/s4u/s4u_Netzone.cpp @@ -100,33 +100,41 @@ int NetZone::add_component(kernel::routing::NetPoint* elm) return pimpl_->add_component(elm); } -std::vector NetZone::get_link_list_impl(const std::vector& link_list) +std::vector NetZone::convert_to_linkInRoute(const std::vector& link_list) { - std::vector links; - for (const auto& link : link_list) { - links.push_back(link->get_impl()); + std::vector links; + for (const auto* link : link_list) { + links.emplace_back(LinkInRoute(link->get_iface())); } return links; } void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, - const std::vector& link_list, bool symmetrical) + const std::vector& link_list, bool symmetrical) { - pimpl_->add_route(src, dst, gw_src, gw_dst, NetZone::get_link_list_impl(link_list), symmetrical); + pimpl_->add_route(src, dst, gw_src, gw_dst, link_list, symmetrical); } void NetZone::add_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, const std::vector& link_list, bool symmetrical) { - pimpl_->add_route(src, dst, gw_src, gw_dst, link_list, symmetrical); + pimpl_->add_route(src, dst, gw_src, gw_dst, convert_to_linkInRoute(link_list), symmetrical); +} + +void NetZone::add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, + kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, + std::vector& link_list, bool /*symmetrical*/) +{ + pimpl_->add_bypass_route(src, dst, gw_src, gw_dst, convert_to_linkInRoute(link_list)); } + void NetZone::add_bypass_route(kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst, kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst, - std::vector& link_list, bool symmetrical) + const std::vector& link_list) { - pimpl_->add_bypass_route(src, dst, gw_src, gw_dst, link_list, symmetrical); + pimpl_->add_bypass_route(src, dst, gw_src, gw_dst, link_list); } void NetZone::extract_xbt_graph(const s_xbt_graph_t* graph, std::map>* nodes, @@ -180,6 +188,24 @@ s4u::Link* NetZone::create_link(const std::string& name, const std::string& band return create_link(name, std::vector{bandwidth}); } +s4u::SplitDuplexLink* NetZone::create_split_duplex_link(const std::string& name, const std::string& bandwidth) +{ + double speed; + try { + speed = xbt_parse_get_bandwidth("", 0, bandwidth, ""); + } catch (const simgrid::ParseError&) { + throw std::invalid_argument(std::string("Impossible to create split-duplex link: ") + name + + std::string(". Invalid bandwidth: ") + bandwidth); + } + return create_split_duplex_link(name, speed); +} + +s4u::SplitDuplexLink* NetZone::create_split_duplex_link(const std::string& name, double bandwidth) +{ + return kernel::actor::simcall( + [this, &name, &bandwidth] { return pimpl_->create_split_duplex_link(name, std::vector{bandwidth}); }); +} + s4u::Link* NetZone::create_link(const std::string& name, const std::vector& bandwidths) { std::vector bw; diff --git a/src/surf/LinkImpl.cpp b/src/surf/LinkImpl.cpp new file mode 100644 index 0000000000..3bef2d1730 --- /dev/null +++ b/src/surf/LinkImpl.cpp @@ -0,0 +1,137 @@ +/* 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. */ + +#include "src/surf/LinkImpl.hpp" +#include "simgrid/s4u/Engine.hpp" +#include "surf/surf.hpp" + +#include + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(res_network); + +/********* + * Model * + *********/ + +namespace simgrid { +namespace kernel { +namespace resource { + +LinkImpl::LinkImpl(const std::string& name) : LinkImplIntf(name), piface_(this) +{ + if (name != "__loopback__") + xbt_assert(not s4u::Link::by_name_or_null(name), "Link '%s' declared several times in the platform.", name.c_str()); + + s4u::Engine::get_instance()->link_register(name, &piface_); + XBT_DEBUG("Create link '%s'", name.c_str()); +} + +/** @brief Fire the required callbacks and destroy the object + * + * Don't delete directly a Link, call l->destroy() instead. + */ +void LinkImpl::destroy() +{ + s4u::Link::on_destruction(this->piface_); + delete this; +} + +bool LinkImpl::is_used() const +{ + return get_model()->get_maxmin_system()->constraint_used(get_constraint()); +} + +void LinkImpl::set_sharing_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); + sharing_policy_ = policy; +} +s4u::Link::SharingPolicy LinkImpl::get_sharing_policy() const +{ + return sharing_policy_; +} + +void LinkImpl::latency_check(double latency) const +{ + static double last_warned_latency = sg_surf_precision; + if (latency != 0.0 && latency < last_warned_latency) { + XBT_WARN("Latency for link %s is smaller than surf/precision (%g < %g)." + " For more accuracy, consider setting \"--cfg=surf/precision:%g\".", + get_cname(), latency, sg_surf_precision, latency); + last_warned_latency = latency; + } +} + +void LinkImpl::turn_on() +{ + if (not is_on()) { + Resource::turn_on(); + s4u::Link::on_state_change(piface_); + } +} + +void LinkImpl::turn_off() +{ + if (is_on()) { + Resource::turn_off(); + s4u::Link::on_state_change(piface_); + + const kernel::lmm::Element* elem = nullptr; + double now = surf_get_clock(); + while (const auto* var = get_constraint()->get_variable(&elem)) { + Action* action = var->get_id(); + if (action->get_state() == Action::State::INITED || action->get_state() == Action::State::STARTED) { + action->set_finish_time(now); + action->set_state(Action::State::FAILED); + } + } + } +} + +void LinkImpl::seal() +{ + if (is_sealed()) + return; + + xbt_assert(this->get_model(), "Cannot seal Link(%s) without setting the Network model first", this->get_cname()); + Resource::seal(); + s4u::Link::on_creation(piface_); +} + +void LinkImpl::on_bandwidth_change() const +{ + s4u::Link::on_bandwidth_change(piface_); +} + +void LinkImpl::set_bandwidth_profile(profile::Profile* profile) +{ + if (profile) { + xbt_assert(bandwidth_.event == nullptr, "Cannot set a second bandwidth profile to Link %s", get_cname()); + bandwidth_.event = profile->schedule(&profile::future_evt_set, this); + } +} + +void LinkImpl::set_latency_profile(profile::Profile* profile) +{ + if (profile) { + xbt_assert(latency_.event == nullptr, "Cannot set a second latency profile to Link %s", get_cname()); + latency_.event = profile->schedule(&profile::future_evt_set, this); + } +} + +void LinkImpl::set_concurrency_limit(int limit) const +{ + if (limit != -1) { + get_constraint()->reset_concurrency_maximum(); + } + get_constraint()->set_concurrency_limit(limit); +} + +} // namespace resource +} // namespace kernel +} // namespace simgrid \ No newline at end of file diff --git a/src/surf/LinkImpl.hpp b/src/surf/LinkImpl.hpp new file mode 100644 index 0000000000..58837753d7 --- /dev/null +++ b/src/surf/LinkImpl.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2004-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_RESOURCE_LINKIMPL_HPP +#define SIMGRID_KERNEL_RESOURCE_LINKIMPL_HPP + +#include "src/surf/LinkImplIntf.hpp" + +/*********** + * Classes * + ***********/ + +namespace simgrid { +namespace kernel { +namespace resource { +/************ + * Resource * + ************/ +/** @ingroup SURF_network_interface + * @brief SURF network link interface class + * @details A Link represents the link between two [hosts](@ref simgrid::surf::HostImpl) + */ +class LinkImpl : public LinkImplIntf { + s4u::Link piface_; + s4u::Link::SharingPolicy sharing_policy_ = s4u::Link::SharingPolicy::SHARED; + +protected: + explicit LinkImpl(const std::string& name); + LinkImpl(const LinkImpl&) = delete; + LinkImpl& operator=(const LinkImpl&) = delete; + ~LinkImpl() override = default; // Use destroy() instead of this destructor. + +public: + void destroy(); // Must be called instead of the destructor + + void latency_check(double latency) const; + + /** @brief Public interface */ + const s4u::Link* get_iface() const { return &piface_; } + s4u::Link* get_iface() { return &piface_; } + + /** @brief Get the bandwidth in bytes per second of current Link */ + double get_bandwidth() const override { return bandwidth_.peak * bandwidth_.scale; } + + /** @brief Get the latency in seconds of current Link */ + double get_latency() const override { return latency_.peak * latency_.scale; } + + /** @brief The sharing policy */ + virtual void set_sharing_policy(s4u::Link::SharingPolicy policy) override; + virtual s4u::Link::SharingPolicy get_sharing_policy() const override; + + /** @brief Check if the Link is used */ + bool is_used() const override; + + void turn_on() override; + void turn_off() override; + + void seal() override; + + void on_bandwidth_change() const; + + /* setup the profile file with bandwidth events (peak speed changes due to external load). + * Profile must contain percentages (value between 0 and 1). */ + virtual void set_bandwidth_profile(kernel::profile::Profile* profile) override; + /* setup the profile file with latency events (peak latency changes due to external load). + * Profile must contain absolute values */ + virtual 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 +} // namespace kernel +} // namespace simgrid + +#endif /* SIMGRID_KERNEL_RESOURCE_LINKIMPL_HPP */ diff --git a/src/surf/LinkImplIntf.hpp b/src/surf/LinkImplIntf.hpp new file mode 100644 index 0000000000..c9d3daceed --- /dev/null +++ b/src/surf/LinkImplIntf.hpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2004-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_RESOURCE_LINKIMPLINTF_HPP +#define SIMGRID_KERNEL_RESOURCE_LINKIMPLINTF_HPP + +#include "simgrid/kernel/resource/Resource.hpp" +#include "simgrid/s4u/Link.hpp" +#include + +/*********** + * Classes * + ***********/ + +namespace simgrid { +namespace kernel { +namespace resource { +/************ + * Resource * + ************/ +/** @ingroup SURF_interface + * @brief SURF network link interface class + * @details A Link represents the link between two [hosts](@ref simgrid::surf::HostImpl) + */ +class LinkImplIntf : public Resource_T, public xbt::PropertyHolder { +public: + using Resource_T::Resource_T; + /** @brief Get the bandwidth in bytes per second of current Link */ + virtual double get_bandwidth() const = 0; + /** @brief Update the bandwidth in bytes per second of current Link */ + virtual void set_bandwidth(double value) = 0; + + /** @brief Get the latency in seconds of current Link */ + virtual double get_latency() const = 0; + /** @brief Update the latency in seconds of current Link */ + virtual void set_latency(double value) = 0; + + /** @brief The sharing policy */ + virtual void set_sharing_policy(s4u::Link::SharingPolicy policy) = 0; + virtual s4u::Link::SharingPolicy get_sharing_policy() const = 0; + + /* setup the profile file with bandwidth events (peak speed changes due to external load). + * Profile must contain percentages (value between 0 and 1). */ + virtual void set_bandwidth_profile(kernel::profile::Profile* profile) = 0; + /* setup the profile file with latency events (peak latency changes due to external load). + * Profile must contain absolute values */ + virtual void set_latency_profile(kernel::profile::Profile* profile) = 0; + /** @brief Set the concurrency limit for this link */ + virtual void set_concurrency_limit(int limit) const = 0; +}; + +} // namespace resource +} // namespace kernel +} // namespace simgrid + +#endif /* SIMGRID_KERNEL_RESOURCE_LINKIMPLINTF_HPP */ diff --git a/src/surf/SplitDuplexLinkImpl.cpp b/src/surf/SplitDuplexLinkImpl.cpp new file mode 100644 index 0000000000..329955a538 --- /dev/null +++ b/src/surf/SplitDuplexLinkImpl.cpp @@ -0,0 +1,99 @@ +/* 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. */ + +#include "src/surf/SplitDuplexLinkImpl.hpp" + +XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(res_network); + +/********* + * Model * + *********/ + +namespace simgrid { +namespace kernel { +namespace resource { + +SplitDuplexLinkImpl::SplitDuplexLinkImpl(const std::string& name, LinkImpl* link_up, LinkImpl* link_down) + : LinkImplIntf(name), piface_(this), link_up_(link_up), link_down_(link_down) +{ +} + +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) +{ + xbt_die("Impossible to change sharing policy of split-duplex links"); +} + +s4u::Link::SharingPolicy SplitDuplexLinkImpl::get_sharing_policy() const +{ + return sharing_policy_; +} + +void SplitDuplexLinkImpl::set_bandwidth(double value) +{ + link_up_->set_bandwidth(value); + link_down_->set_bandwidth(value); +} + +void SplitDuplexLinkImpl::set_latency(double value) +{ + link_up_->set_latency(value); + link_down_->set_latency(value); +} + +void SplitDuplexLinkImpl::turn_on() +{ + link_up_->turn_on(); + link_down_->turn_on(); +} + +void SplitDuplexLinkImpl::turn_off() +{ + link_up_->turn_off(); + link_down_->turn_off(); +} + +void SplitDuplexLinkImpl::apply_event(profile::Event* event, double value) +{ + link_up_->apply_event(event, value); + link_down_->apply_event(event, value); +} + +void SplitDuplexLinkImpl::seal() +{ + if (is_sealed()) + return; + + link_up_->seal(); + link_down_->seal(); + + Resource::seal(); +} + +void SplitDuplexLinkImpl::set_bandwidth_profile(profile::Profile* profile) +{ + link_up_->set_bandwidth_profile(profile); + link_down_->set_bandwidth_profile(profile); +} + +void SplitDuplexLinkImpl::set_latency_profile(profile::Profile* profile) +{ + link_up_->set_latency_profile(profile); + link_down_->set_latency_profile(profile); +} + +void SplitDuplexLinkImpl::set_concurrency_limit(int limit) const +{ + link_up_->set_concurrency_limit(limit); + link_down_->set_concurrency_limit(limit); +} + +} // namespace resource +} // namespace kernel +} // namespace simgrid \ No newline at end of file diff --git a/src/surf/SplitDuplexLinkImpl.hpp b/src/surf/SplitDuplexLinkImpl.hpp new file mode 100644 index 0000000000..3158718c94 --- /dev/null +++ b/src/surf/SplitDuplexLinkImpl.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2004-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_RESOURCE_SDLINKIMPL_HPP +#define SIMGRID_KERNEL_RESOURCE_SDLINKIMPL_HPP + +#include "src/surf/LinkImpl.hpp" +#include "src/surf/LinkImplIntf.hpp" + +/*********** + * Classes * + ***********/ + +namespace simgrid { +namespace kernel { +namespace resource { +/************ + * Resource * + ************/ +/** @ingroup SURF_network_interface + * @brief SURF network link interface class + * @details A Link represents the link between two [hosts](@ref simgrid::surf::HostImpl) + */ +class SplitDuplexLinkImpl : public LinkImplIntf { + s4u::SplitDuplexLink piface_; + s4u::Link::SharingPolicy sharing_policy_ = s4u::Link::SharingPolicy::SPLITDUPLEX; + LinkImpl* link_up_; + LinkImpl* link_down_; + +protected: + SplitDuplexLinkImpl(const LinkImpl&) = delete; + SplitDuplexLinkImpl& operator=(const LinkImpl&) = delete; + +public: + SplitDuplexLinkImpl(const std::string& name, LinkImpl* link_up, LinkImpl* link_down); + /** @brief Public interface */ + const s4u::SplitDuplexLink* get_iface() const { return &piface_; } + s4u::SplitDuplexLink* get_iface() { return &piface_; } + + /** @brief Get the bandwidth in bytes per second of current Link */ + double get_bandwidth() const override { return link_up_->get_bandwidth(); } + void set_bandwidth(double value) override; + + /** @brief Get the latency in seconds of current Link */ + double get_latency() const override { return link_up_->get_latency(); } + void set_latency(double value) override; + + /** @brief The sharing policy */ + virtual void set_sharing_policy(s4u::Link::SharingPolicy policy) override; + virtual s4u::Link::SharingPolicy get_sharing_policy() const override; + + /** @brief Get link composing this split-duplex link */ + s4u::Link* get_link_up() const { return link_up_->get_iface(); } + s4u::Link* get_link_down() const { return link_down_->get_iface(); } + + /** @brief Check if the Link is used */ + bool is_used() const override; + + void turn_on() override; + void turn_off() override; + + void seal() override; + + void apply_event(profile::Event* event, double value) override; + + /* setup the profile file with bandwidth events (peak speed changes due to external load). + * Profile must contain percentages (value between 0 and 1). */ + void set_bandwidth_profile(kernel::profile::Profile* profile) override; + /* setup the profile file with latency events (peak latency changes due to external load). + * Profile must contain absolute values */ + void set_latency_profile(kernel::profile::Profile* profile) override; + void set_concurrency_limit(int limit) const override; +}; + +} // namespace resource +} // namespace kernel +} // namespace simgrid + +#endif /* SIMGRID_KERNEL_RESOURCE_SDLINKIMPL_HPP */ diff --git a/src/surf/SplitDuplexLinkImpl_test.cpp b/src/surf/SplitDuplexLinkImpl_test.cpp new file mode 100644 index 0000000000..25abf7434d --- /dev/null +++ b/src/surf/SplitDuplexLinkImpl_test.cpp @@ -0,0 +1,75 @@ +/* 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/s4u/Engine.hpp" +#include "simgrid/s4u/Link.hpp" +#include "src/surf/SplitDuplexLinkImpl.hpp" + +TEST_CASE("SplitDuplexLink: create", "") +{ + simgrid::s4u::Engine e("test"); + auto* zone = simgrid::s4u::create_star_zone("test"); + + SECTION("create string") + { + simgrid::s4u::Link* link_up; + simgrid::s4u::Link* link_down; + simgrid::s4u::SplitDuplexLink* link; + REQUIRE_NOTHROW(link = zone->create_split_duplex_link("link", "100GBps")); + REQUIRE(simgrid::s4u::SplitDuplexLink::by_name("link") == link); + REQUIRE_NOTHROW(link_up = simgrid::s4u::Link::by_name("link_UP")); + REQUIRE_NOTHROW(link_down = simgrid::s4u::Link::by_name("link_DOWN")); + REQUIRE(link_up->get_bandwidth() == 100e9); + REQUIRE(link_down->get_bandwidth() == 100e9); + REQUIRE(link_up == link->get_link_up()); + REQUIRE(link_down == link->get_link_down()); + } + + SECTION("create double") { REQUIRE_NOTHROW(zone->create_split_duplex_link("link", 10e6)); } +} + +TEST_CASE("SplitDuplexLink: sets", "") +{ + simgrid::s4u::Engine e("test"); + auto* zone = simgrid::s4u::create_star_zone("test"); + auto* link = zone->create_split_duplex_link("link", 100e6); + auto* link_up = link->get_link_up(); + auto* link_down = link->get_link_down(); + + SECTION("bandwidth") + { + double bw = 1e3; + link->set_bandwidth(bw); + REQUIRE(link_up->get_bandwidth() == bw); + REQUIRE(link_down->get_bandwidth() == bw); + } + + SECTION("latency") + { + double lat = 1e-9; + link->set_latency(lat); + REQUIRE(link_up->get_latency() == lat); + REQUIRE(link_down->get_latency() == lat); + } + + SECTION("turn on/off") + { + link->turn_off(); + REQUIRE(not link_up->is_on()); + REQUIRE(not link_down->is_on()); + link->turn_on(); + REQUIRE(link_up->is_on()); + REQUIRE(link_down->is_on()); + } + + SECTION("concurrency_limit") + { + link->set_concurrency_limit(3); + REQUIRE(link_up->get_impl()->get_constraint()->get_concurrency_limit() == 3); + REQUIRE(link_down->get_impl()->get_constraint()->get_concurrency_limit() == 3); + } +} \ No newline at end of file diff --git a/src/surf/network_cm02.cpp b/src/surf/network_cm02.cpp index d63c108e05..5b1f916b85 100644 --- a/src/surf/network_cm02.cpp +++ b/src/surf/network_cm02.cpp @@ -87,9 +87,9 @@ NetworkCm02Model::NetworkCm02Model(const std::string& name) : NetworkModel(name) } set_maxmin_system(new lmm::System(select)); - loopback_ = create_link("__loopback__", std::vector{config::get_value("network/loopback-bw")}) - ->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE) - ->set_latency(config::get_value("network/loopback-lat")); + loopback_ = create_link("__loopback__", std::vector{config::get_value("network/loopback-bw")}); + loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE); + loopback_->set_latency(config::get_value("network/loopback-lat")); loopback_->seal(); } @@ -130,12 +130,16 @@ void NetworkCm02Model::set_bw_factor_cb(const std::function& cb LinkImpl* NetworkCm02Model::create_link(const std::string& name, const std::vector& bandwidths) { xbt_assert(bandwidths.size() == 1, "Non-WIFI links must use only 1 bandwidth."); - return (new NetworkCm02Link(name, bandwidths[0], get_maxmin_system()))->set_model(this); + auto link = new NetworkCm02Link(name, bandwidths[0], get_maxmin_system()); + link->set_model(this); + return link; } LinkImpl* NetworkCm02Model::create_wifi_link(const std::string& name, const std::vector& bandwidths) { - return (new NetworkWifiLink(name, bandwidths, get_maxmin_system()))->set_model(this); + auto link = new NetworkWifiLink(name, bandwidths, get_maxmin_system()); + link->set_model(this); + return link; } void NetworkCm02Model::update_actions_state_lazy(double now, double /*delta*/) @@ -495,7 +499,7 @@ void NetworkCm02Link::set_bandwidth(double value) } } -LinkImpl* NetworkCm02Link::set_latency(double value) +void NetworkCm02Link::set_latency(double value) { latency_check(value); @@ -528,7 +532,6 @@ LinkImpl* NetworkCm02Link::set_latency(double value) if (not action->is_suspended()) get_model()->get_maxmin_system()->update_variable_penalty(action->get_variable(), action->sharing_penalty_); } - return this; } /********** diff --git a/src/surf/network_cm02.hpp b/src/surf/network_cm02.hpp index 172a267046..c962616e35 100644 --- a/src/surf/network_cm02.hpp +++ b/src/surf/network_cm02.hpp @@ -77,7 +77,7 @@ public: NetworkCm02Link(const std::string& name, double bandwidth, lmm::System* system); void apply_event(kernel::profile::Event* event, double value) override; void set_bandwidth(double value) override; - LinkImpl* set_latency(double value) override; + void set_latency(double value) override; }; /********** diff --git a/src/surf/network_interface.cpp b/src/surf/network_interface.cpp index 2983342067..16f5397f87 100644 --- a/src/surf/network_interface.cpp +++ b/src/surf/network_interface.cpp @@ -54,126 +54,6 @@ double NetworkModel::next_occurring_event_full(double now) return minRes; } -/************ - * Resource * - ************/ - -LinkImpl::LinkImpl(const std::string& name) : Resource_T(name), piface_(this) -{ - if (name != "__loopback__") - xbt_assert(not s4u::Link::by_name_or_null(name), "Link '%s' declared several times in the platform.", name.c_str()); - - s4u::Engine::get_instance()->link_register(name, &piface_); - XBT_DEBUG("Create link '%s'", name.c_str()); -} - -/** @brief Fire the required callbacks and destroy the object - * - * Don't delete directly a Link, call l->destroy() instead. - */ -void LinkImpl::destroy() -{ - s4u::Link::on_destruction(this->piface_); - delete this; -} - -bool LinkImpl::is_used() const -{ - return get_model()->get_maxmin_system()->constraint_used(get_constraint()); -} - -LinkImpl* LinkImpl::set_sharing_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); - sharing_policy_ = policy; - return this; -} -s4u::Link::SharingPolicy LinkImpl::get_sharing_policy() const -{ - return sharing_policy_; -} - -void LinkImpl::latency_check(double latency) const -{ - static double last_warned_latency = sg_surf_precision; - if (latency != 0.0 && latency < last_warned_latency) { - XBT_WARN("Latency for link %s is smaller than surf/precision (%g < %g)." - " For more accuracy, consider setting \"--cfg=surf/precision:%g\".", - get_cname(), latency, sg_surf_precision, latency); - last_warned_latency = latency; - } -} - -void LinkImpl::turn_on() -{ - if (not is_on()) { - Resource::turn_on(); - s4u::Link::on_state_change(piface_); - } -} - -void LinkImpl::turn_off() -{ - if (is_on()) { - Resource::turn_off(); - s4u::Link::on_state_change(piface_); - - const kernel::lmm::Element* elem = nullptr; - double now = surf_get_clock(); - while (const auto* var = get_constraint()->get_variable(&elem)) { - Action* action = var->get_id(); - if (action->get_state() == Action::State::INITED || action->get_state() == Action::State::STARTED) { - action->set_finish_time(now); - action->set_state(Action::State::FAILED); - } - } - } -} - -void LinkImpl::seal() -{ - if (is_sealed()) - return; - - xbt_assert(this->get_model(), "Cannot seal Link(%s) without setting the Network model first", this->get_cname()); - Resource::seal(); - s4u::Link::on_creation(piface_); -} - -void LinkImpl::on_bandwidth_change() const -{ - s4u::Link::on_bandwidth_change(piface_); -} - -LinkImpl* LinkImpl::set_bandwidth_profile(profile::Profile* profile) -{ - if (profile) { - xbt_assert(bandwidth_.event == nullptr, "Cannot set a second bandwidth profile to Link %s", get_cname()); - bandwidth_.event = profile->schedule(&profile::future_evt_set, this); - } - return this; -} - -LinkImpl* LinkImpl::set_latency_profile(profile::Profile* profile) -{ - if (profile) { - xbt_assert(latency_.event == nullptr, "Cannot set a second latency profile to Link %s", get_cname()); - latency_.event = profile->schedule(&profile::future_evt_set, this); - } - return this; -} - -void LinkImpl::set_concurrency_limit(int limit) const -{ - if (limit != -1) { - get_constraint()->reset_concurrency_maximum(); - } - get_constraint()->set_concurrency_limit(limit); -} - /********** * Action * **********/ diff --git a/src/surf/network_interface.hpp b/src/surf/network_interface.hpp index 3917de1168..1f712a6e25 100644 --- a/src/surf/network_interface.hpp +++ b/src/surf/network_interface.hpp @@ -11,6 +11,7 @@ #include "simgrid/kernel/resource/Resource.hpp" #include "simgrid/s4u/Link.hpp" #include "src/kernel/lmm/maxmin.hpp" +#include "src/surf/LinkImpl.hpp" #include #include @@ -93,69 +94,6 @@ public: LinkImpl* loopback_ = nullptr; }; -/************ - * Resource * - ************/ -/** @ingroup SURF_network_interface - * @brief SURF network link interface class - * @details A Link represents the link between two [hosts](@ref simgrid::surf::HostImpl) - */ -class LinkImpl : public Resource_T, public xbt::PropertyHolder { - s4u::Link piface_; - s4u::Link::SharingPolicy sharing_policy_ = s4u::Link::SharingPolicy::SHARED; - -protected: - explicit LinkImpl(const std::string& name); - LinkImpl(const LinkImpl&) = delete; - LinkImpl& operator=(const LinkImpl&) = delete; - ~LinkImpl() override = default; // Use destroy() instead of this destructor. - -public: - void destroy(); // Must be called instead of the destructor - - void latency_check(double latency) const; - - /** @brief Public interface */ - const s4u::Link* get_iface() const { return &piface_; } - s4u::Link* get_iface() { return &piface_; } - - /** @brief Get the bandwidth in bytes per second of current Link */ - double get_bandwidth() const { return bandwidth_.peak * bandwidth_.scale; } - /** @brief Update the bandwidth in bytes per second of current Link */ - virtual void set_bandwidth(double value) = 0; - - /** @brief Get the latency in seconds of current Link */ - double get_latency() const { return latency_.peak * latency_.scale; } - /** @brief Update the latency in seconds of current Link */ - virtual LinkImpl* set_latency(double value) = 0; - - /** @brief The sharing policy */ - virtual LinkImpl* set_sharing_policy(s4u::Link::SharingPolicy policy); - virtual s4u::Link::SharingPolicy get_sharing_policy() const; - - /** @brief Check if the Link is used */ - bool is_used() const override; - - void turn_on() override; - void turn_off() override; - - void seal() override; - - void on_bandwidth_change() const; - - /* setup the profile file with bandwidth events (peak speed changes due to external load). - * Profile must contain percentages (value between 0 and 1). */ - virtual LinkImpl* set_bandwidth_profile(kernel::profile::Profile* profile); - /* setup the profile file with latency events (peak latency changes due to external load). - * Profile must contain absolute values */ - virtual LinkImpl* set_latency_profile(kernel::profile::Profile* profile); - - void set_concurrency_limit(int limit) const; - - Metric latency_ = {0.0, 1, nullptr}; - Metric bandwidth_ = {1.0, 1, nullptr}; -}; - /********** * Action * **********/ diff --git a/src/surf/network_ns3.cpp b/src/surf/network_ns3.cpp index 1180f02b1f..81839efe3b 100644 --- a/src/surf/network_ns3.cpp +++ b/src/surf/network_ns3.cpp @@ -330,19 +330,23 @@ NetworkNS3Model::NetworkNS3Model(const std::string& name) : NetworkModel(name) ns3::GlobalRouteManager::InitializeRoutes(); }); routing::on_cluster_creation.connect(&clusterCreation_cb); - s4u::NetZone::on_route_creation.connect(&routeCreation_cb); + routing::NetZoneImpl::on_route_creation.connect(&routeCreation_cb); s4u::NetZone::on_seal.connect(&zoneCreation_cb); } LinkImpl* NetworkNS3Model::create_link(const std::string& name, const std::vector& bandwidths) { xbt_assert(bandwidths.size() == 1, "ns-3 links must use only 1 bandwidth."); - return (new LinkNS3(name, bandwidths[0]))->set_model(this); + auto* link = new LinkNS3(name, bandwidths[0]); + link->set_model(this); + return link; } LinkImpl* NetworkNS3Model::create_wifi_link(const std::string& name, const std::vector& bandwidths) { - return create_link(name, bandwidths)->set_sharing_policy(s4u::Link::SharingPolicy::WIFI); + auto* link = create_link(name, bandwidths); + link->set_sharing_policy(s4u::Link::SharingPolicy::WIFI); + return link; } Action* NetworkNS3Model::communicate(s4u::Host* src, s4u::Host* dst, double size, double rate) @@ -455,28 +459,24 @@ void LinkNS3::apply_event(profile::Event*, double) THROW_UNIMPLEMENTED; } -LinkImpl* LinkNS3::set_bandwidth_profile(profile::Profile* profile) +void LinkNS3::set_bandwidth_profile(profile::Profile* profile) { xbt_assert(profile == nullptr, "The ns-3 network model doesn't support bandwidth profiles"); - return this; } -LinkImpl* LinkNS3::set_latency_profile(profile::Profile* profile) +void LinkNS3::set_latency_profile(profile::Profile* profile) { xbt_assert(profile == nullptr, "The ns-3 network model doesn't support latency profiles"); - return this; } -LinkImpl* LinkNS3::set_latency(double latency) +void LinkNS3::set_latency(double latency) { latency_.peak = latency; - return this; } -LinkImpl* LinkNS3::set_sharing_policy(s4u::Link::SharingPolicy policy) +void LinkNS3::set_sharing_policy(s4u::Link::SharingPolicy policy) { sharing_policy_ = policy; - return this; } /********** * Action * diff --git a/src/surf/network_ns3.hpp b/src/surf/network_ns3.hpp index 7db4a38bc0..c0a8e11200 100644 --- a/src/surf/network_ns3.hpp +++ b/src/surf/network_ns3.hpp @@ -36,10 +36,10 @@ public: void apply_event(profile::Event* event, double value) override; void set_bandwidth(double) override { THROW_UNIMPLEMENTED; } - LinkImpl* set_latency(double) override; - LinkImpl* set_bandwidth_profile(profile::Profile* profile) override; - LinkImpl* set_latency_profile(profile::Profile* profile) override; - LinkImpl* set_sharing_policy(s4u::Link::SharingPolicy policy) override; + 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; s4u::Link::SharingPolicy get_sharing_policy() const override { return sharing_policy_; } }; diff --git a/src/surf/network_wifi.cpp b/src/surf/network_wifi.cpp index 655941ce0b..c82d321548 100644 --- a/src/surf/network_wifi.cpp +++ b/src/surf/network_wifi.cpp @@ -91,10 +91,9 @@ bool NetworkWifiLink::toggle_decay_model(){ return use_decay_model_; } -LinkImpl* NetworkWifiLink::set_latency(double value) +void NetworkWifiLink::set_latency(double value) { xbt_assert(value == 0, "Latency cannot be set for WiFi Links."); - return this; } } // namespace resource } // namespace kernel diff --git a/src/surf/network_wifi.hpp b/src/surf/network_wifi.hpp index 9a8d5e8e96..6f5ad3596f 100644 --- a/src/surf/network_wifi.hpp +++ b/src/surf/network_wifi.hpp @@ -51,7 +51,7 @@ public: s4u::Link::SharingPolicy get_sharing_policy() const override; void apply_event(kernel::profile::Event*, double) override { THROW_UNIMPLEMENTED; } void set_bandwidth(double) override { THROW_UNIMPLEMENTED; } - LinkImpl* set_latency(double) override; + void set_latency(double) override; void refresh_decay_bandwidths(); bool toggle_decay_model(); int get_host_count() const; diff --git a/src/surf/ptask_L07.cpp b/src/surf/ptask_L07.cpp index 169d528ed3..cf9f2a11be 100644 --- a/src/surf/ptask_L07.cpp +++ b/src/surf/ptask_L07.cpp @@ -62,9 +62,9 @@ NetworkL07Model::NetworkL07Model(const std::string& name, HostL07Model* hmodel, { set_maxmin_system(sys); loopback_ = - create_link("__loopback__", std::vector{simgrid::config::get_value("network/loopback-bw")}) - ->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE) - ->set_latency(simgrid::config::get_value("network/loopback-lat")); + create_link("__loopback__", std::vector{simgrid::config::get_value("network/loopback-bw")}); + loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE); + loopback_->set_latency(simgrid::config::get_value("network/loopback-lat")); loopback_->seal(); } @@ -241,7 +241,9 @@ kernel::resource::CpuImpl* CpuL07Model::create_cpu(s4u::Host* host, const std::v kernel::resource::LinkImpl* NetworkL07Model::create_link(const std::string& name, const std::vector& bandwidths) { xbt_assert(bandwidths.size() == 1, "Non WIFI link must have only 1 bandwidth."); - return (new LinkL07(name, bandwidths[0], get_maxmin_system()))->set_model(this); + auto link = new LinkL07(name, bandwidths[0], get_maxmin_system()); + link->set_model(this); + return link; } kernel::resource::LinkImpl* NetworkL07Model::create_wifi_link(const std::string& name, @@ -362,7 +364,7 @@ void LinkL07::set_bandwidth(double value) get_model()->get_maxmin_system()->update_constraint_bound(get_constraint(), bandwidth_.peak * bandwidth_.scale); } -kernel::resource::LinkImpl* LinkL07::set_latency(double value) +void LinkL07::set_latency(double value) { latency_check(value); const kernel::lmm::Element* elem = nullptr; @@ -372,7 +374,6 @@ kernel::resource::LinkImpl* LinkL07::set_latency(double value) auto* action = static_cast(var->get_id()); action->updateBound(); } - return this; } LinkL07::~LinkL07() = default; diff --git a/src/surf/ptask_L07.hpp b/src/surf/ptask_L07.hpp index f153895210..d211954c7f 100644 --- a/src/surf/ptask_L07.hpp +++ b/src/surf/ptask_L07.hpp @@ -113,7 +113,7 @@ public: bool is_used() const override; void apply_event(kernel::profile::Event* event, double value) override; void set_bandwidth(double value) override; - LinkImpl* set_latency(double value) override; + void set_latency(double value) override; }; /********** diff --git a/src/surf/sg_platf.cpp b/src/surf/sg_platf.cpp index d015d71be6..0774f2ab88 100644 --- a/src/surf/sg_platf.cpp +++ b/src/surf/sg_platf.cpp @@ -114,27 +114,26 @@ simgrid::kernel::routing::NetPoint* sg_platf_new_router(const std::string& name, return netpoint; } -static void sg_platf_new_link(const simgrid::kernel::routing::LinkCreationArgs* args, const std::string& link_name) +static void sg_platf_set_link_properties(simgrid::s4u::Link* link, + const simgrid::kernel::routing::LinkCreationArgs* args) { - current_routing->create_link(link_name, args->bandwidths) - ->set_properties(args->properties) - ->get_impl() // this call to get_impl saves some simcalls but can be removed - ->set_sharing_policy(args->policy) + link->set_properties(args->properties) ->set_state_profile(args->state_trace) ->set_latency_profile(args->latency_trace) ->set_bandwidth_profile(args->bandwidth_trace) - ->set_latency(args->latency) - ->seal(); + ->set_latency(args->latency); } -void sg_platf_new_link(const simgrid::kernel::routing::LinkCreationArgs* link) +void sg_platf_new_link(const simgrid::kernel::routing::LinkCreationArgs* args) { - if (link->policy == simgrid::s4u::Link::SharingPolicy::SPLITDUPLEX) { - sg_platf_new_link(link, link->id + "_UP"); - sg_platf_new_link(link, link->id + "_DOWN"); + simgrid::s4u::Link* link; + if (args->policy == simgrid::s4u::Link::SharingPolicy::SPLITDUPLEX) { + link = current_routing->create_split_duplex_link(args->id, args->bandwidths); } else { - sg_platf_new_link(link, link->id); + link = current_routing->create_link(args->id, args->bandwidths)->set_sharing_policy(args->policy); } + sg_platf_set_link_properties(link, args); + link->seal(); } void sg_platf_new_disk(const simgrid::kernel::routing::DiskCreationArgs* disk) @@ -295,7 +294,7 @@ static void sg_platf_new_cluster_flat(simgrid::kernel::routing::ClusterCreationA ->seal(); zone->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr, - std::vector{loopback}); + std::vector{loopback}); } // add a limiter link (shared link to account for maximal bandwidth of the node) @@ -308,25 +307,22 @@ static void sg_platf_new_cluster_flat(simgrid::kernel::routing::ClusterCreationA } // create link - simgrid::s4u::Link* link_up; - simgrid::s4u::Link* link_down; + simgrid::s4u::Link* link; if (cluster->sharing_policy == simgrid::s4u::Link::SharingPolicy::SPLITDUPLEX) { - link_up = zone->create_link(link_id + "_UP", std::vector{cluster->bw})->set_latency(cluster->lat)->seal(); - link_down = - zone->create_link(link_id + "_DOWN", std::vector{cluster->bw})->set_latency(cluster->lat)->seal(); + link = zone->create_split_duplex_link(link_id, cluster->bw)->set_latency(cluster->lat)->seal(); } else { - link_up = zone->create_link(link_id, std::vector{cluster->bw})->set_latency(cluster->lat)->seal(); - link_down = link_up; + link = zone->create_link(link_id, std::vector{cluster->bw})->set_latency(cluster->lat)->seal(); } /* adding routes */ - std::vector links_up{limiter, link_up, backbone}; - std::vector links_down{backbone, link_down, limiter}; - links_up.erase(std::remove(links_up.begin(), links_up.end(), nullptr), links_up.end()); - links_down.erase(std::remove(links_down.begin(), links_down.end(), nullptr), links_down.end()); - - zone->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, links_up, false); - zone->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, links_down, false); + std::vector links; + if (limiter) + links.push_back(limiter); + links.push_back(simgrid::s4u::LinkInRoute(link, simgrid::s4u::LinkInRoute::Direction::UP)); + if (backbone) + links.push_back(backbone); + + zone->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, links, true); } // Add a router. @@ -359,22 +355,22 @@ void sg_platf_new_tag_cluster(simgrid::kernel::routing::ClusterCreationArgs* clu static void sg_platf_cluster_set_hostlink(simgrid::kernel::routing::StarZone* zone, simgrid::kernel::routing::NetPoint* netpoint, const simgrid::s4u::Link* link_up, const simgrid::s4u::Link* link_down, - simgrid::kernel::resource::LinkImpl* backbone) + simgrid::s4u::Link* backbone) { XBT_DEBUG("Push Host_link for host '%s' to position %u", netpoint->get_cname(), netpoint->id()); if (backbone) { - zone->add_route(netpoint, nullptr, nullptr, nullptr, {link_up->get_impl(), backbone}, false); - zone->add_route(nullptr, netpoint, nullptr, nullptr, {backbone, link_down->get_impl()}, false); + zone->add_route(netpoint, nullptr, nullptr, nullptr, {link_up, backbone}, false); + zone->add_route(nullptr, netpoint, nullptr, nullptr, {backbone, link_down}, false); } else { - zone->add_route(netpoint, nullptr, nullptr, nullptr, {link_up->get_impl()}, false); - zone->add_route(nullptr, netpoint, nullptr, nullptr, {link_down->get_impl()}, false); + zone->add_route(netpoint, nullptr, nullptr, nullptr, {link_up}, false); + zone->add_route(nullptr, netpoint, nullptr, nullptr, {link_down}, false); } } /** @brief Add a link connecting a host to the rest of its StarZone */ static void sg_platf_build_hostlink(simgrid::kernel::routing::StarZone* zone, const simgrid::kernel::routing::HostLinkCreationArgs* hostlink, - simgrid::kernel::resource::LinkImpl* backbone) + simgrid::s4u::Link* backbone) { simgrid::kernel::routing::NetPoint* netpoint = simgrid::s4u::Host::by_name(hostlink->id)->get_netpoint(); xbt_assert(netpoint, "Host '%s' not found!", hostlink->id.c_str()); @@ -390,7 +386,7 @@ static void sg_platf_build_hostlink(simgrid::kernel::routing::StarZone* zone, /** @brief Create a cabinet (set of hosts) inside a Cluster(StarZone) */ static void sg_platf_build_cabinet(simgrid::kernel::routing::StarZone* zone, const simgrid::kernel::routing::CabinetCreationArgs* args, - simgrid::kernel::resource::LinkImpl* backbone) + simgrid::s4u::Link* backbone) { for (int const& radical : args->radicals) { std::string id = args->prefix + std::to_string(radical) + args->suffix; @@ -410,11 +406,11 @@ static void sg_platf_zone_cluster_populate(const simgrid::kernel::routing::Clust auto* zone = dynamic_cast(current_routing); xbt_assert(zone, "Host_links are only valid for Cluster(Star)"); - simgrid::kernel::resource::LinkImpl* backbone = nullptr; + simgrid::s4u::Link* backbone = nullptr; /* create backbone */ if (cluster->backbone) { sg_platf_new_link(cluster->backbone.get()); - backbone = simgrid::s4u::Link::by_name(cluster->backbone->id)->get_impl(); + backbone = simgrid::s4u::Link::by_name(cluster->backbone->id); } /* create host_links for hosts */ @@ -448,8 +444,7 @@ void sg_platf_new_route(simgrid::kernel::routing::RouteCreationArgs* route) void sg_platf_new_bypass_route(simgrid::kernel::routing::RouteCreationArgs* route) { - current_routing->add_bypass_route(route->src, route->dst, route->gw_src, route->gw_dst, route->link_list, - route->symmetrical); + current_routing->add_bypass_route(route->src, route->dst, route->gw_src, route->gw_dst, route->link_list); } void sg_platf_new_actor(simgrid::kernel::routing::ActorCreationArgs* actor) diff --git a/src/surf/xml/platf_private.hpp b/src/surf/xml/platf_private.hpp index 044ed0a4af..763f9634b1 100644 --- a/src/surf/xml/platf_private.hpp +++ b/src/surf/xml/platf_private.hpp @@ -80,7 +80,7 @@ public: NetPoint* dst = nullptr; NetPoint* gw_src = nullptr; NetPoint* gw_dst = nullptr; - std::vector link_list; + std::vector link_list; }; enum class ClusterTopology { DRAGONFLY = 3, FAT_TREE = 2, FLAT = 1, TORUS = 0 }; diff --git a/src/surf/xml/surfxml_sax_cb.cpp b/src/surf/xml/surfxml_sax_cb.cpp index 58eefa276e..1a0edf9536 100644 --- a/src/surf/xml/surfxml_sax_cb.cpp +++ b/src/surf/xml/surfxml_sax_cb.cpp @@ -28,8 +28,7 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_parse, surf, "Logging specific to the SURF parsing module"); std::string surf_parsed_filename; // Currently parsed file (for the error messages) -std::vector - parsed_link_list; /* temporary store of current link list of a route */ +std::vector parsed_link_list; /* temporary store of current link list of a route */ /* Helping functions */ void surf_parse_assert(bool cond, const std::string& msg) @@ -482,17 +481,20 @@ void ETag_surfxml_link(){ void STag_surfxml_link___ctn() { - simgrid::kernel::resource::LinkImpl* link = nullptr; + simgrid::s4u::Link* link; + simgrid::s4u::LinkInRoute::Direction direction = simgrid::s4u::LinkInRoute::Direction::NONE; switch (A_surfxml_link___ctn_direction) { case AU_surfxml_link___ctn_direction: case A_surfxml_link___ctn_direction_NONE: - link = simgrid::s4u::Link::by_name(std::string(A_surfxml_link___ctn_id))->get_impl(); + link = simgrid::s4u::Link::by_name(std::string(A_surfxml_link___ctn_id)); break; case A_surfxml_link___ctn_direction_UP: - link = simgrid::s4u::Link::by_name(std::string(A_surfxml_link___ctn_id) + "_UP")->get_impl(); + link = simgrid::s4u::SplitDuplexLink::by_name(std::string(A_surfxml_link___ctn_id)); + direction = simgrid::s4u::LinkInRoute::Direction::UP; break; case A_surfxml_link___ctn_direction_DOWN: - link = simgrid::s4u::Link::by_name(std::string(A_surfxml_link___ctn_id) + "_DOWN")->get_impl(); + link = simgrid::s4u::SplitDuplexLink::by_name(std::string(A_surfxml_link___ctn_id)); + direction = simgrid::s4u::LinkInRoute::Direction::DOWN; break; default: surf_parse_error(std::string("Invalid direction for link ") + A_surfxml_link___ctn_id); @@ -510,7 +512,7 @@ void STag_surfxml_link___ctn() dirname = ""; } surf_parse_assert(link != nullptr, std::string("No such link: '") + A_surfxml_link___ctn_id + "'" + dirname); - parsed_link_list.push_back(link); + parsed_link_list.emplace_back(simgrid::s4u::LinkInRoute(link, direction)); } void ETag_surfxml_backbone() diff --git a/teshsuite/s4u/seal-platform/seal-platform.cpp b/teshsuite/s4u/seal-platform/seal-platform.cpp index 512362d64f..0701900a57 100644 --- a/teshsuite/s4u/seal-platform/seal-platform.cpp +++ b/teshsuite/s4u/seal-platform/seal-platform.cpp @@ -70,7 +70,7 @@ static sg4::NetZone* create_zone(const sg4::NetZone* root, const std::string& id auto* host = zone->create_host(hostname, 1e9); host->create_disk("disk-" + hostname, 1e9, 1e6); auto* link = zone->create_link("link-" + hostname, 1e9); - zone->add_route(host->get_netpoint(), router, nullptr, nullptr, std::vector{link}); + zone->add_route(host->get_netpoint(), router, nullptr, nullptr, std::vector{link}); } return zone; } @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) auto* zoneB = create_zone(root, "B"); auto* link = root->create_link("root-link", 1e10); root->add_route(zoneA->get_netpoint(), zoneB->get_netpoint(), e.netpoint_by_name("routerA"), - e.netpoint_by_name("routerB"), std::vector{link}); + e.netpoint_by_name("routerB"), std::vector{link}); std::vector host_list = e.get_all_hosts(); /* create the sender actor running on first host */ diff --git a/teshsuite/simdag/flatifier/flatifier.tesh b/teshsuite/simdag/flatifier/flatifier.tesh index aa134d712d..8935cba2da 100644 --- a/teshsuite/simdag/flatifier/flatifier.tesh +++ b/teshsuite/simdag/flatifier/flatifier.tesh @@ -1490,3 +1490,28 @@ $ ${bindir:=.}/flatifier ../platforms/cluster_torus_noncontiguous_rad.xml "--log > > > +$ ${bindir:=.}/flatifier ../platforms/two_hosts_one_link_splitduplex.xml "--log=root.fmt:[%10.6r]%e[%i:%a@%h]%e%m%n" +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> +> + diff --git a/teshsuite/simdag/platforms/two_hosts_one_link_splitduplex.xml b/teshsuite/simdag/platforms/two_hosts_one_link_splitduplex.xml index 7e766ff6ab..f121533162 100644 --- a/teshsuite/simdag/platforms/two_hosts_one_link_splitduplex.xml +++ b/teshsuite/simdag/platforms/two_hosts_one_link_splitduplex.xml @@ -7,11 +7,8 @@ - + - - - diff --git a/tools/cmake/DefinePackages.cmake b/tools/cmake/DefinePackages.cmake index 9cb8960904..50b5d4698d 100644 --- a/tools/cmake/DefinePackages.cmake +++ b/tools/cmake/DefinePackages.cmake @@ -41,6 +41,9 @@ set(EXTRA_DIST src/surf/network_cm02.hpp src/surf/network_constant.hpp src/surf/network_interface.hpp + src/surf/LinkImpl.hpp + src/surf/LinkImplIntf.hpp + src/surf/SplitDuplexLinkImpl.hpp src/surf/network_ns3.hpp src/surf/network_smpi.hpp src/surf/network_ib.hpp @@ -348,6 +351,8 @@ set(SURF_SRC src/surf/network_cm02.cpp src/surf/network_constant.cpp src/surf/network_interface.cpp + src/surf/LinkImpl.cpp + src/surf/SplitDuplexLinkImpl.cpp src/surf/network_wifi.cpp src/surf/sg_platf.cpp src/surf/surf_c_bindings.cpp diff --git a/tools/cmake/Tests.cmake b/tools/cmake/Tests.cmake index 2c6ea4c480..fb4291ccf3 100644 --- a/tools/cmake/Tests.cmake +++ b/tools/cmake/Tests.cmake @@ -132,6 +132,7 @@ set(UNIT_TESTS src/xbt/unit-tests_main.cpp src/kernel/routing/FullZone_test.cpp src/kernel/routing/StarZone_test.cpp src/kernel/routing/TorusZone_test.cpp + src/surf/SplitDuplexLinkImpl_test.cpp src/xbt/config_test.cpp src/xbt/dict_test.cpp src/xbt/dynar_test.cpp -- 2.20.1