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.
<route src="alice" dst="bob" symmetrical="YES">
<link_ctn id="link1" direction="UP"/>
</route>
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.
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
link and the *1_DOWN* link. As you can see, the selection of link to use
in the <route> 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
/* 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<sg4::Link*>{link_up}, false);
- /* link DOWN, connection from outer to CPU */
- host_zone->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{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<sg4::LinkInRoute>{{link, sg4::LinkInRoute::Direction::UP}}, true);
}
/* seal newly created netzone */
host_zone->seal();
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<sg4::Link*>{link_up},
- false);
- zone->add_route(receiver->get_netpoint(), sender->get_netpoint(), nullptr, nullptr,
- std::vector<sg4::Link*>{link_down}, false);
+ zone->add_route(sender->get_netpoint(), receiver->get_netpoint(), nullptr, nullptr,
+ std::vector<sg4::LinkInRoute>{{link, sg4::LinkInRoute::Direction::UP}}, true);
zone->seal();
/* create actors Sender/Receiver */
/* 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<sg4::Link*>{l_up}, false);
- root->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{l_down}, false);
+ root->add_route(host->get_netpoint(), nullptr, nullptr, nullptr,
+ std::vector<sg4::LinkInRoute>{{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<sg4::Link*>{loopback});
+ root->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr,
+ std::vector<sg4::LinkInRoute>{loopback});
}
root->seal();
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<sg4::Link*>{link_up}, false);
- cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::Link*>{link_down}, false);
+ cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr,
+ std::vector<sg4::LinkInRoute>{{link, sg4::LinkInRoute::Direction::UP}}, true);
}
auto* router = cluster->create_router("cluster_router");
/* 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<sg4::Link*>{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<sg4::Link*>{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<sg4::LinkInRoute>{{link, sg4::LinkInRoute::Direction::UP}, l_bb}, true);
}
/* create router */
}
/* add link UP and backbone for communications from the host */
- cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector<sg4::Link*>{l_up, l_bb}, false);
+ cluster->add_route(host->get_netpoint(), nullptr, nullptr, nullptr, std::vector<sg4::LinkInRoute>{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<sg4::Link*>{l_bb, l_down}, false);
+ cluster->add_route(nullptr, host->get_netpoint(), nullptr, nullptr, std::vector<sg4::LinkInRoute>{l_bb, l_down},
+ false);
}
/* create router */
XBT_PUBLIC void intrusive_ptr_add_ref(Io* i);
class Link;
+class SplitDuplexLink;
class Mailbox;
class NetworkModel;
class NetworkModelIntf;
class LinkImpl;
+class SplitDuplexLinkImpl;
+class LinkImplIntf;
class NetworkAction;
class DiskImpl;
class DiskModel;
*/
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<resource::LinkImpl*>& link_list, bool symmetrical) override;
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) override;
};
} // namespace routing
} // namespace kernel
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<resource::LinkImpl*>& link_list, bool symmetrical) override;
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) override;
};
} // namespace routing
} // namespace kernel
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<resource::LinkImpl*>& link_list, bool symmetrical) override;
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) override;
};
} // namespace routing
} // namespace kernel
/** @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<resource::LinkImpl*> get_link_list_impl(const std::vector<s4u::LinkInRoute>& link_list,
+ bool backroute) const;
+
public:
enum class RoutingMode {
base, /**< Base case: use simple link lists for routing */
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<double>& bandwidths);
+ s4u::SplitDuplexLink* create_split_duplex_link(const std::string& name, const std::vector<double>& 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<resource::LinkImpl*>& link_list, bool symmetrical);
+ const std::vector<s4u::LinkInRoute>& link_list);
/** @brief Seal your netzone once you're done adding content, and before routing stuff through it */
void seal();
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<kernel::resource::LinkImpl*>& link_list, bool symmetrical);
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical);
/** @brief Set parent of this Netzone */
void set_parent(NetZoneImpl* parent);
/** @brief Set network model for this Netzone */
virtual void get_graph(const s_xbt_graph_t* graph, std::map<std::string, xbt_node_t, std::less<>>* nodes,
std::map<std::string, xbt_edge_t, std::less<>>* edges) = 0;
+ /*** Called on each newly created regular route (not on bypass routes) */
+ static xbt::signal<void(bool symmetrical, kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
+ kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
+ std::vector<kernel::resource::LinkImpl*> 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<resource::NetworkModel> network_model_;
}
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<resource::LinkImpl*>& link_list, bool symmetrical) const;
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) const;
};
} // namespace routing
} // namespace kernel
std::map<std::string, xbt_edge_t, std::less<>>* edges) override;
void add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
- const std::vector<kernel::resource::LinkImpl*>& link_list, bool symmetrical) override;
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) override;
void do_seal() override;
private:
std::vector<Link*> get_all_links() const;
std::vector<Link*> get_filtered_links(const std::function<bool(Link*)>& 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;
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);
static xbt::signal<void(kernel::resource::NetworkAction&, kernel::resource::Action::State)>
on_communication_state_change;
};
+
+/**
+ * @beginrst
+ * A SplitDuplexLink encapsulates the :cpp:class:`links <simgrid::s4u::Link>` 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
* @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*>& link_list, bool symmetrical = true);
+ kernel::routing::NetPoint* gw_dst, const std::vector<LinkInRoute>& 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<kernel::resource::LinkImpl*>& 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<kernel::resource::LinkImpl*>& 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<kernel::resource::LinkImpl*>& 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<kernel::resource::LinkImpl*>& link_list, bool symmetrical);
+ const std::vector<LinkInRoute>& link_list);
+#ifndef DOXYGEN
/*** Called on each newly created regular route (not on bypass routes) */
static xbt::signal<void(bool symmetrical, kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
std::vector<kernel::resource::LinkImpl*> 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<void(NetZone const&)> on_creation;
static xbt::signal<void(NetZone const&)> on_seal;
s4u::Link* create_link(const std::string& name, const std::vector<std::string>& 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;
/**
NetZone* seal();
private:
- /** @brief Auxiliary function to get list of LinkImpl */
- static std::vector<kernel::resource::LinkImpl*> get_link_list_impl(const std::vector<Link*>& link_list);
+ /** @brief Auxiliary function to convert types */
+ static std::vector<LinkInRoute> convert_to_linkInRoute(const std::vector<kernel::resource::LinkImpl*>& link_list);
};
// External constructors so that the types (and the types of their content) remain hidden
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);
}
}
}
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);
}
}
}
models_prio_[model_name] = std::move(model);
}
+void EngineImpl::add_split_duplex_link(const std::string& name, std::unique_ptr<resource::SplitDuplexLinkImpl> 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
{
#include "src/kernel/activity/SleepImpl.hpp"
#include "src/kernel/activity/SynchroRaw.hpp"
#include "src/kernel/actor/ActorImpl.hpp"
+#include "src/surf/SplitDuplexLinkImpl.hpp"
#include <boost/intrusive/list.hpp>
#include <map>
class EngineImpl {
std::map<std::string, s4u::Host*, std::less<>> hosts_;
std::map<std::string, resource::LinkImpl*, std::less<>> 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<std::string, std::unique_ptr<resource::SplitDuplexLinkImpl>> split_duplex_links_;
std::unordered_map<std::string, routing::NetPoint*> netpoints_;
std::unordered_map<std::string, activity::MailboxImpl*> mailboxes_;
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<resource::SplitDuplexLinkImpl> link);
#if SIMGRID_HAVE_MC
xbt_dynar_t get_actors_vector() const { return actors_vector_; }
}
void DijkstraZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
- const std::vector<resource::LinkImpl*>& link_list_, bool symmetrical)
+ const std::vector<s4u::LinkInRoute>& 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)
std::string cpu_name = "CPU" + std::to_string(i);
const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
- std::vector<simgrid::s4u::Link*>{link}, true));
+ std::vector<simgrid::s4u::LinkInRoute>{link}, true));
}
}
}
void FloydZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
- const std::vector<resource::LinkImpl*>& link_list_, bool symmetrical)
+ const std::vector<s4u::LinkInRoute>& 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)
"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<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, true));
+ link_table_[src->id()][dst->id()] = std::unique_ptr<Route>(
+ 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();
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<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list_, false));
+ link_table_[dst->id()][src->id()] = std::unique_ptr<Route>(
+ 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 */
std::string cpu_name = "CPU" + std::to_string(i);
const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
- std::vector<simgrid::s4u::Link*>{link}, true));
+ std::vector<simgrid::s4u::LinkInRoute>{link}, true));
}
}
}
void FullZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
- const std::vector<resource::LinkImpl*>& link_list, bool symmetrical)
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical)
{
add_route_check_params(src, dst, gw_src, gw_dst, link_list, symmetrical);
dst->get_cname());
/* Add the route to the base */
- routing_table_[src->id()][dst->id()] =
- std::unique_ptr<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, true));
+ routing_table_[src->id()][dst->id()] = std::unique_ptr<Route>(
+ new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, false), true));
if (symmetrical && src != dst) {
if (gw_dst && gw_src) {
"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<Route>(new_extended_route(get_hierarchy(), gw_src, gw_dst, link_list, false));
+ routing_table_[dst->id()][src->id()] = std::unique_ptr<Route>(
+ new_extended_route(get_hierarchy(), gw_src, gw_dst, get_link_list_impl(link_list, true), false));
}
}
} // namespace routing
std::string cpu_name = "CPU" + std::to_string(i);
const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nic->get_netpoint(), nullptr, nullptr,
- std::vector<simgrid::s4u::Link*>{link}, true));
+ std::vector<simgrid::s4u::LinkInRoute>{link}, true));
}
}
#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"
disk_model->model_init_preparse();
}
+xbt::signal<void(bool symmetrical, kernel::routing::NetPoint* src, kernel::routing::NetPoint* dst,
+ kernel::routing::NetPoint* gw_src, kernel::routing::NetPoint* gw_dst,
+ std::vector<kernel::resource::LinkImpl*> 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.
return network_model_->create_link(name, bandwidths)->get_iface();
}
+s4u::SplitDuplexLink* NetZoneImpl::create_split_duplex_link(const std::string& name,
+ const std::vector<double>& 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<resource::SplitDuplexLinkImpl>(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_,
return vertices_.size() - 1; // The rank of the newly created object
}
+std::vector<resource::LinkImpl*> NetZoneImpl::get_link_list_impl(const std::vector<s4u::LinkInRoute>& link_list,
+ bool backroute) const
+{
+ std::vector<resource::LinkImpl*> 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<const s4u::SplitDuplexLink*>(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<resource::LinkImpl*>& /*link_list_*/, bool /*symmetrical*/)
+ const std::vector<s4u::LinkInRoute>& /*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<resource::LinkImpl*>& link_list_, bool /* symmetrical */)
+ const std::vector<s4u::LinkInRoute>& 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());
/* 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});
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<resource::LinkImpl*>& link_list, bool symmetrical) const
+ const std::vector<s4u::LinkInRoute>& link_list, bool symmetrical) const
{
const char* srcName = src->get_cname();
const char* dstName = dst->get_cname();
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);
"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
}
void StarZone::add_route(NetPoint* src, NetPoint* dst, NetPoint* gw_src, NetPoint* gw_dst,
- const std::vector<kernel::resource::LinkImpl*>& link_list_, bool symmetrical)
+ const std::vector<s4u::LinkInRoute>& 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;
}
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");
const auto* host1 = zone->create_host("netpoint1", {100});
const auto* host2 = zone->create_host("netpoint2", {100});
- std::vector<simgrid::kernel::resource::LinkImpl*> links;
- links.push_back(zone->create_link("link1", {100})->get_impl());
- std::vector<simgrid::kernel::resource::LinkImpl*> links2;
- links2.push_back(zone->create_link("link2", {100})->get_impl());
+ std::vector<simgrid::s4u::LinkInRoute> links;
+ links.emplace_back(zone->create_link("link1", {100}));
+ std::vector<simgrid::s4u::LinkInRoute> links2;
+ links2.emplace_back(zone->create_link("link2", {100}));
SECTION("Get route: no UP link")
{
SECTION("Get route: no shared link")
{
- std::vector<simgrid::kernel::resource::LinkImpl*> links;
- links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
- std::vector<simgrid::kernel::resource::LinkImpl*> links2;
- links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
+ std::vector<simgrid::s4u::LinkInRoute> links;
+ links.emplace_back(zone->create_link("link1", {100})->set_latency(10));
+ std::vector<simgrid::s4u::LinkInRoute> 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();
SECTION("Get route: shared link(backbone)")
{
- auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl();
- std::vector<simgrid::kernel::resource::LinkImpl*> links;
- links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
- links.push_back(backbone);
- std::vector<simgrid::kernel::resource::LinkImpl*> links2;
- links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
- links2.push_back(backbone);
+ auto* backbone = zone->create_link("backbone", {1000})->set_latency(100);
+ std::vector<simgrid::s4u::LinkInRoute> links;
+ links.emplace_back(zone->create_link("link1", {100})->set_latency(10));
+ links.emplace_back(backbone);
+ std::vector<simgrid::s4u::LinkInRoute> 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);
SECTION("Get route: loopback")
{
- auto* backbone = zone->create_link("backbone", {1000})->set_latency(100)->get_impl();
- std::vector<simgrid::kernel::resource::LinkImpl*> links;
- links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
- links.push_back(backbone);
+ auto* backbone = zone->create_link("backbone", {1000})->set_latency(100);
+ std::vector<simgrid::s4u::LinkInRoute> 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();
SECTION("Get route: netzone")
{
- std::vector<simgrid::kernel::resource::LinkImpl*> links;
- links.push_back(zone->create_link("link1", {100})->set_latency(10)->get_impl());
- std::vector<simgrid::kernel::resource::LinkImpl*> links2;
- links2.push_back(zone->create_link("link2", {200})->set_latency(20)->get_impl());
+ std::vector<simgrid::s4u::LinkInRoute> links;
+ links.emplace_back(zone->create_link("link1", {100})->set_latency(10));
+ std::vector<simgrid::s4u::LinkInRoute> 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();
for (int i = 0; i < 10; i++) {
std::string cpu_name = "CPU" + std::to_string(i);
const simgrid::s4u::Host* cpu = zone->create_host(cpu_name, 1e9)->seal();
- REQUIRE_NOTHROW(
- zone->add_route(cpu->get_netpoint(), nullptr, nullptr, nullptr, std::vector<simgrid::s4u::Link*>{link}, true));
+ REQUIRE_NOTHROW(zone->add_route(cpu->get_netpoint(), nullptr, nullptr, nullptr,
+ std::vector<simgrid::s4u::LinkInRoute>{link}, true));
}
}
std::string link_down = "link_" + netpoint->get_name() + "_DOWN";
const auto* linkUp = create_link(link_up, std::vector<double>{bw_out})->seal();
const auto* linkDown = create_link(link_down, std::vector<double>{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<s4u::LinkInRoute>{linkUp}, false);
+ add_route(nullptr, netpoint, nullptr, nullptr, std::vector<s4u::LinkInRoute>{linkDown}, false);
}
void VivaldiZone::get_local_route(const NetPoint* src, const NetPoint* dst, Route* route, double* lat)
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
{
#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"
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<kernel::resource::LinkImpl*>(pimpl_);
+}
+
Link* Link::by_name_or_null(const std::string& name)
{
return Engine::get_instance()->link_by_name_or_null(name);
{
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;
return this;
}
+Link* SplitDuplexLink::get_link_up() const
+{
+ return dynamic_cast<kernel::resource::SplitDuplexLinkImpl*>(pimpl_)->get_link_up();
+}
+
+Link* SplitDuplexLink::get_link_down() const
+{
+ return dynamic_cast<kernel::resource::SplitDuplexLinkImpl*>(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
return pimpl_->add_component(elm);
}
-std::vector<kernel::resource::LinkImpl*> NetZone::get_link_list_impl(const std::vector<Link*>& link_list)
+std::vector<LinkInRoute> NetZone::convert_to_linkInRoute(const std::vector<kernel::resource::LinkImpl*>& link_list)
{
- std::vector<kernel::resource::LinkImpl*> links;
- for (const auto& link : link_list) {
- links.push_back(link->get_impl());
+ std::vector<LinkInRoute> 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*>& link_list, bool symmetrical)
+ const std::vector<LinkInRoute>& 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<kernel::resource::LinkImpl*>& 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<kernel::resource::LinkImpl*>& 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<kernel::resource::LinkImpl*>& link_list, bool symmetrical)
+ const std::vector<LinkInRoute>& 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<std::string, xbt_node_t, std::less<>>* nodes,
return create_link(name, std::vector<std::string>{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<double>{bandwidth}); });
+}
+
s4u::Link* NetZone::create_link(const std::string& name, const std::vector<std::string>& bandwidths)
{
std::vector<double> bw;
--- /dev/null
+/* 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 <numeric>
+
+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
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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 <xbt/PropertyHolder.hpp>
+
+/***********
+ * 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<LinkImplIntf>, 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 */
--- /dev/null
+/* 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
--- /dev/null
+/* 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 */
--- /dev/null
+/* Copyright (c) 2017-2021. The SimGrid Team. All rights reserved. */
+
+/* This program is free software; you can redistribute it and/or modify it
+ * under the terms of the license (GNU LGPL) which comes with this package. */
+
+#include "catch.hpp"
+
+#include "simgrid/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
}
set_maxmin_system(new lmm::System(select));
- loopback_ = create_link("__loopback__", std::vector<double>{config::get_value<double>("network/loopback-bw")})
- ->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE)
- ->set_latency(config::get_value<double>("network/loopback-lat"));
+ loopback_ = create_link("__loopback__", std::vector<double>{config::get_value<double>("network/loopback-bw")});
+ loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE);
+ loopback_->set_latency(config::get_value<double>("network/loopback-lat"));
loopback_->seal();
}
LinkImpl* NetworkCm02Model::create_link(const std::string& name, const std::vector<double>& 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<double>& 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*/)
}
}
-LinkImpl* NetworkCm02Link::set_latency(double value)
+void NetworkCm02Link::set_latency(double value)
{
latency_check(value);
if (not action->is_suspended())
get_model()->get_maxmin_system()->update_variable_penalty(action->get_variable(), action->sharing_penalty_);
}
- return this;
}
/**********
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;
};
/**********
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 *
**********/
#include "simgrid/kernel/resource/Resource.hpp"
#include "simgrid/s4u/Link.hpp"
#include "src/kernel/lmm/maxmin.hpp"
+#include "src/surf/LinkImpl.hpp"
#include <xbt/PropertyHolder.hpp>
#include <list>
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<LinkImpl>, 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 *
**********/
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<double>& 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<double>& 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)
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 *
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_; }
};
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
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;
{
set_maxmin_system(sys);
loopback_ =
- create_link("__loopback__", std::vector<double>{simgrid::config::get_value<double>("network/loopback-bw")})
- ->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE)
- ->set_latency(simgrid::config::get_value<double>("network/loopback-lat"));
+ create_link("__loopback__", std::vector<double>{simgrid::config::get_value<double>("network/loopback-bw")});
+ loopback_->set_sharing_policy(s4u::Link::SharingPolicy::FATPIPE);
+ loopback_->set_latency(simgrid::config::get_value<double>("network/loopback-lat"));
loopback_->seal();
}
kernel::resource::LinkImpl* NetworkL07Model::create_link(const std::string& name, const std::vector<double>& 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,
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;
auto* action = static_cast<L07Action*>(var->get_id());
action->updateBound();
}
- return this;
}
LinkL07::~LinkL07() = default;
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;
};
/**********
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)
->seal();
zone->add_route(host->get_netpoint(), host->get_netpoint(), nullptr, nullptr,
- std::vector<simgrid::s4u::Link*>{loopback});
+ std::vector<simgrid::s4u::LinkInRoute>{loopback});
}
// add a limiter link (shared link to account for maximal bandwidth of the node)
}
// 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<double>{cluster->bw})->set_latency(cluster->lat)->seal();
- link_down =
- zone->create_link(link_id + "_DOWN", std::vector<double>{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<double>{cluster->bw})->set_latency(cluster->lat)->seal();
- link_down = link_up;
+ link = zone->create_link(link_id, std::vector<double>{cluster->bw})->set_latency(cluster->lat)->seal();
}
/* adding routes */
- std::vector<simgrid::s4u::Link*> links_up{limiter, link_up, backbone};
- std::vector<simgrid::s4u::Link*> 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<simgrid::s4u::LinkInRoute> 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.
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());
/** @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;
auto* zone = dynamic_cast<simgrid::kernel::routing::StarZone*>(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 */
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)
NetPoint* dst = nullptr;
NetPoint* gw_src = nullptr;
NetPoint* gw_dst = nullptr;
- std::vector<resource::LinkImpl*> link_list;
+ std::vector<simgrid::s4u::LinkInRoute> link_list;
};
enum class ClusterTopology { DRAGONFLY = 3, FAT_TREE = 2, FLAT = 1, TORUS = 0 };
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<simgrid::kernel::resource::LinkImpl*>
- parsed_link_list; /* temporary store of current link list of a route */
+std::vector<simgrid::s4u::LinkInRoute> parsed_link_list; /* temporary store of current link list of a route */
/* Helping functions */
void surf_parse_assert(bool cond, const std::string& msg)
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);
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()
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<sg4::Link*>{link});
+ zone->add_route(host->get_netpoint(), router, nullptr, nullptr, std::vector<sg4::LinkInRoute>{link});
}
return zone;
}
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<sg4::Link*>{link});
+ e.netpoint_by_name("routerB"), std::vector<sg4::LinkInRoute>{link});
std::vector<sg4::Host*> host_list = e.get_all_hosts();
/* create the sender actor running on first host */
> </route>
> </AS>
> </platform>
+$ ${bindir:=.}/flatifier ../platforms/two_hosts_one_link_splitduplex.xml "--log=root.fmt:[%10.6r]%e[%i:%a@%h]%e%m%n"
+> <?xml version='1.0'?>
+> <!DOCTYPE platform SYSTEM "https://simgrid.org/simgrid.dtd">
+> <platform version="4">
+> <AS id="AS0" routing="Full">
+> <host id="alice" speed="500000000"/>
+> <host id="bob" speed="1000000000"/>
+> <link id="__loopback__" bandwidth="10000000000" latency="0.000000000" sharing_policy="FATPIPE"/>
+> <link id="link1_DOWN" bandwidth="125000000" latency="0.000050000"/>
+> <link id="link1_UP" bandwidth="125000000" latency="0.000050000"/>
+> <route src="alice" dst="alice">
+> <link_ctn id="__loopback__"/>
+> </route>
+> <route src="alice" dst="bob">
+> <link_ctn id="link1_UP"/>
+> </route>
+> <route src="bob" dst="alice">
+> <link_ctn id="link1_DOWN"/>
+> </route>
+> <route src="bob" dst="bob">
+> <link_ctn id="__loopback__"/>
+> </route>
+> </AS>
+> </platform>
+
<link id="link1" bandwidth="125MBps" latency="50us" sharing_policy="SPLITDUPLEX"/>
- <route src="alice" dst="bob" symmetrical="NO">
+ <route src="alice" dst="bob" symmetrical="YES">
<link_ctn id="link1" direction="UP"/>
</route>
- <route src="bob" dst="alice" symmetrical="NO">
- <link_ctn id="link1" direction="DOWN"/>
- </route>
</zone>
</platform>
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
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
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