X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/c69e23793c9da81d75f1fa275a7131f299416147..ab5814bd4ea6117ecf9ac2df328333e89eb45f5f:/src/kernel/resource/models/network_ns3.cpp diff --git a/src/kernel/resource/models/network_ns3.cpp b/src/kernel/resource/models/network_ns3.cpp index b486ec1e1e..3d4c0650ff 100644 --- a/src/kernel/resource/models/network_ns3.cpp +++ b/src/kernel/resource/models/network_ns3.cpp @@ -9,6 +9,8 @@ #include #include +#include "src/simgrid/math_utils.h" +#include "src/simgrid/module.hpp" #include "xbt/config.hpp" #include "xbt/str.h" #include "xbt/string.hpp" @@ -25,8 +27,8 @@ #include #include -#include "ns3/mobility-module.h" -#include "ns3/wifi-module.h" +#include +#include #include "network_ns3.hpp" #include "src/kernel/resource/models/ns3/ns3_simulator.hpp" @@ -39,7 +41,7 @@ #include "simgrid/s4u/NetZone.hpp" #include "src/instr/instr_private.hpp" // TRACE_is_enabled(). FIXME: remove by subscribing tracing to the signals #include "src/kernel/EngineImpl.hpp" -#include "src/surf/xml/platf_private.hpp" // ClusterCreationArgs +#include "src/kernel/xml/platf_private.hpp" // ClusterCreationArgs XBT_LOG_NEW_DEFAULT_SUBCATEGORY(res_ns3, res_network, "Network model based on ns-3"); @@ -48,7 +50,6 @@ XBT_LOG_NEW_DEFAULT_SUBCATEGORY(res_ns3, res_network, "Network model based on ns *****************/ extern std::map> flow_from_sock; -extern std::map> sink_from_sock; static int number_of_links = 1; static int number_of_networks = 1; @@ -118,8 +119,14 @@ static void zoneCreation_cb(simgrid::s4u::NetZone const& zone) wifiPhy.Set("Antennas", ns3::UintegerValue(nss_value)); wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(nss_value)); wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(nss_value)); -#if NS3_MINOR_VERSION > 33 +#if NS3_MINOR_VERSION < 33 + // This fails with "The channel width does not uniquely identify an operating channel" on v3.34, + // so we specified the ChannelWidth of wifiPhy to 40, above, when creating wifiPhy with v3.34 and higher + ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40)); +#elif NS3_MINOR_VERSION < 36 wifiPhy.Set("ChannelWidth", ns3::UintegerValue(40)); +#else + wifiPhy.Set("ChannelSettings", ns3::StringValue("{0, 40, BAND_UNSPECIFIED, 0}")); #endif wifiMac.SetType("ns3::ApWifiMac", "Ssid", ns3::SsidValue(ssid)); @@ -165,12 +172,6 @@ static void zoneCreation_cb(simgrid::s4u::NetZone const& zone) ns3::Simulator::Schedule(ns3::Seconds(start_time_value), &resumeWifiDevice, device); } -#if NS3_MINOR_VERSION < 33 - // This fails with "The channel width does not uniquely identify an operating channel" on v3.34, - // so we specified the ChannelWidth of wifiPhy to 40, above, when creating wifiPhy with v3.34 and higher - ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40)); -#endif - mobility.SetPositionAllocator(positionAllocS); mobility.Install(nodes); ns3::Ipv4AddressHelper address; @@ -286,8 +287,9 @@ static void XBT_ATTRIB_CONSTRUCTOR(800) simgrid_ns3_network_model_register() }); } -static simgrid::config::Flag - ns3_tcp_model("ns3/TcpModel", "The ns-3 tcp model can be: NewReno or Reno or Tahoe", "default"); +static simgrid::config::Flag ns3_network_model_name("ns3/NetworkModel", {"ns3/TcpModel"}, + "The ns-3 tcp model can be: NewReno or Cubic", + "default", [](const std::string&) {}); static simgrid::config::Flag ns3_seed( "ns3/seed", "The random seed provided to ns-3. Either 'time' to seed with time(), blank to not set (default), or a number.", "", @@ -315,20 +317,34 @@ NetworkNS3Model::NetworkNS3Model(const std::string& name) : NetworkModel(name) "LinkEnergy plugin and ns-3 network models are not compatible. Are you looking for Ecofen, maybe?"); NetPointNs3::EXTENSION_ID = routing::NetPoint::extension_create(); + auto const& NetworkProtocol = ns3_network_model_name.get(); + + if (NetworkProtocol == "UDP") { + /*UdpClient=0 +UdpEchoClientApplication=0 +UdpEchoServerApplication=0 +UdpL4Protocol=0 +UdpServer=0 +UdpSocket=0 +UdpSocketImpl=0 +UdpTraceClient=0*/ + LogComponentEnable("UdpSocket", ns3::LOG_LEVEL_DEBUG); + LogComponentEnable("UdpL4Protocol", ns3::LOG_LEVEL_DEBUG); + } else { + ns3::Config::SetDefault("ns3::TcpSocket::SegmentSize", ns3::UintegerValue(1000)); + ns3::Config::SetDefault("ns3::TcpSocket::DelAckCount", ns3::UintegerValue(1)); + ns3::Config::SetDefault("ns3::TcpSocketBase::Timestamp", ns3::BooleanValue(false)); + } - ns3::Config::SetDefault("ns3::TcpSocket::SegmentSize", ns3::UintegerValue(1000)); - ns3::Config::SetDefault("ns3::TcpSocket::DelAckCount", ns3::UintegerValue(1)); - ns3::Config::SetDefault("ns3::TcpSocketBase::Timestamp", ns3::BooleanValue(false)); - - if (auto const& TcpProtocol = ns3_tcp_model.get(); TcpProtocol == "default") { - /* nothing to do */ + if (NetworkProtocol == "NewReno" || NetworkProtocol == "Cubic") { + XBT_INFO("Switching Tcp protocol to '%s'", NetworkProtocol.c_str()); + ns3::Config::SetDefault("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::Tcp" + NetworkProtocol)); - } else if (TcpProtocol == "Reno" || TcpProtocol == "NewReno" || TcpProtocol == "Tahoe") { - XBT_INFO("Switching Tcp protocol to '%s'", TcpProtocol.c_str()); - ns3::Config::SetDefault("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::Tcp" + TcpProtocol)); + } else if (NetworkProtocol == "UDP") { + XBT_INFO("Switching network protocol to UDP."); - } else { - xbt_die("The ns3/TcpModel must be: NewReno or Reno or Tahoe"); + } else if (NetworkProtocol != "default") { + xbt_die("The ns3/NetworkModel must be: NewReno, Cubic or UDP but it's '%s'", NetworkProtocol.c_str()); } routing::NetPoint::on_creation.connect([](routing::NetPoint& pt) { @@ -338,7 +354,6 @@ NetworkNS3Model::NetworkNS3Model(const std::string& name) : NetworkModel(name) s4u::Engine::on_platform_created_cb([]() { /* Create the ns3 topology based on routing strategy */ - ns3::GlobalRouteManager::DeleteGlobalRoutes(); // just in case this callback is called twice ns3::GlobalRouteManager::BuildGlobalRoutingDatabase(); ns3::GlobalRouteManager::InitializeRoutes(); }); @@ -375,6 +390,31 @@ Action* NetworkNS3Model::communicate(s4u::Host* src, s4u::Host* dst, double size return new NetworkNS3Action(this, size, src, dst); } +#if SIMGRID_HAVE_NS3_GetNextEventTime +/* If patched, ns3 is idempotent and nice to use */ +bool NetworkNS3Model::next_occurring_event_is_idempotent() +{ + return true; +} + +double NetworkNS3Model::next_occurring_event(double sg_time) +{ + if (get_started_action_set()->empty()) { + return -1.0; + } + + double ns3_time = ns3::Simulator::GetNextEventTime().GetSeconds(); + XBT_DEBUG("NS3 tells that the next occuring event is at %f (it's %f in SimGrid), so NS3 returns a delta of %f.", + ns3_time, sg_time, ns3_time - sg_time); + return ns3_time - sg_time; +} +#else +/* NS3 is only idempotent with the appropriate patch */ +bool NetworkNS3Model::next_occurring_event_is_idempotent() +{ + return false; +} + double NetworkNS3Model::next_occurring_event(double now) { double time_to_next_flow_completion = 0.0; @@ -404,11 +444,25 @@ double NetworkNS3Model::next_occurring_event(double now) return time_to_next_flow_completion; } +#endif void NetworkNS3Model::update_actions_state(double now, double delta) { static std::vector socket_to_destroy; +#if SIMGRID_HAVE_NS3_GetNextEventTime + /* If the ns-3 model is idempotent, it won't get updated in next_occurring_event() */ + + if (delta >= 0) { + XBT_DEBUG("DO START simulator delta: %f (current simgrid time: %f; current ns3 time: %f)", delta, + simgrid::kernel::EngineImpl::get_clock(), ns3::Simulator::Now().GetSeconds()); + ns3_simulator(delta); + } else { + XBT_DEBUG("don't start simulator delta: %f (current simgrid time: %f; current ns3 time: %f)", delta, + simgrid::kernel::EngineImpl::get_clock(), ns3::Simulator::Now().GetSeconds()); + } +#endif + for (const auto& [ns3_socket, sgFlow] : flow_from_sock) { NetworkNS3Action* action = sgFlow->action_; XBT_DEBUG("Processing flow %p (socket %s, action %p)", sgFlow, ns3_socket.c_str(), action); @@ -425,7 +479,7 @@ void NetworkNS3Model::update_actions_state(double now, double delta) std::vector route; action->get_src().route_to(&action->get_dst(), route, nullptr); - for (auto const& link : route) + for (auto const* link : route) instr::resource_set_utilization("LINK", "bandwidth_used", link->get_cname(), action->get_category(), data_delta_sent / delta, now - delta, delta); @@ -453,7 +507,6 @@ void NetworkNS3Model::update_actions_state(double now, double delta) } delete flow; flow_from_sock.erase(ns3_socket); - sink_from_sock.erase(ns3_socket); } } @@ -504,7 +557,7 @@ NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* s if (src == dst) { if (static bool warned = false; not warned) { XBT_WARN("Sending from a host %s to itself is not supported by ns-3. Every such communication finishes " - "immediately upon startup.", + "immediately upon startup in the SimGrid+ns-3 system.", src->get_cname()); warned = true; } @@ -531,17 +584,18 @@ NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* s dst->get_netpoint()->get_cname()); ns3::PacketSinkHelper sink("ns3::TcpSocketFactory", ns3::InetSocketAddress(ns3::Ipv4Address::GetAny(), port_number)); - ns3::ApplicationContainer apps = sink.Install(dst_node); + sink.Install(dst_node); ns3::Ptr sock = ns3::Socket::CreateSocket(src_node, ns3::TcpSocketFactory::GetTypeId()); - XBT_DEBUG("Create socket %s for a flow of %.0f Bytes from %s to %s with Interface %s", - transform_socket_ptr(sock).c_str(), totalBytes, src->get_cname(), dst->get_cname(), addr.c_str()); + auto sock_addr = transform_socket_ptr(sock); + XBT_DEBUG("Create socket %s for a flow of %.0f Bytes from %s to %s with Interface %s", sock_addr.c_str(), totalBytes, + src->get_cname(), dst->get_cname(), addr.c_str()); - flow_from_sock.try_emplace(transform_socket_ptr(sock), new SgFlow(static_cast(totalBytes), this)); - sink_from_sock.try_emplace(transform_socket_ptr(sock), apps); + flow_from_sock.try_emplace(sock_addr, new SgFlow(static_cast(totalBytes), this)); sock->Bind(ns3::InetSocketAddress(port_number)); + ns3::Simulator::ScheduleNow(&start_flow, sock, addr.c_str(), port_number); port_number = 1 + (port_number % UINT16_MAX); @@ -572,22 +626,27 @@ void NetworkNS3Action::update_remains_lazy(double /*now*/) ns3::Ptr get_ns3node_from_sghost(const simgrid::s4u::Host* host) { - xbt_assert(host->get_netpoint()->extension() != nullptr, "Please only use this function on ns-3 nodes"); - return host->get_netpoint()->extension()->ns3_node_; + auto* netext = host->get_netpoint()->extension(); + xbt_assert(netext != nullptr, "Please only use this function on ns-3 nodes"); + return netext->ns3_node_; } } // namespace simgrid -void ns3_simulator(double maxSeconds) +void ns3_simulator(double maxSeconds) // maxSecond is a delay, not an absolute time { ns3::EventId id; - if (maxSeconds > 0.0) // If there is a maximum amount of time to run + if (maxSeconds >= 0.0) // If there is a maximum amount of time to run id = ns3::Simulator::Schedule(ns3::Seconds(maxSeconds), &ns3::Simulator::Stop); - XBT_DEBUG("Start simulator for at most %fs (current time: %f)", maxSeconds, simgrid::kernel::EngineImpl::get_clock()); + XBT_DEBUG("Start simulator for at most %fs (current simgrid time: %f; current ns3 time: %f)", maxSeconds, + simgrid::kernel::EngineImpl::get_clock(), ns3::Simulator::Now().GetSeconds()); +#if SIMGRID_HAVE_NS3_GetNextEventTime + xbt_assert(maxSeconds >= 0.0); +#endif ns3::Simulator::Run(); - XBT_DEBUG("Simulator stopped at %fs", ns3::Simulator::Now().GetSeconds()); + XBT_DEBUG("ns3 simulator stopped at %fs", ns3::Simulator::Now().GetSeconds()); - if (maxSeconds > 0.0) + if (maxSeconds >= 0.0) id.Cancel(); }