X-Git-Url: http://bilbo.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/8bc85164acb335cf909052b966b2ee4932e06cd7..0d3fb525534744cb1a0f7e0b664dbb3c2791e9cc:/src/surf/network_ns3.cpp diff --git a/src/surf/network_ns3.cpp b/src/surf/network_ns3.cpp index 65d5e7dc61..c5e05259f3 100644 --- a/src/surf/network_ns3.cpp +++ b/src/surf/network_ns3.cpp @@ -7,6 +7,7 @@ #include #include "xbt/config.hpp" +#include "xbt/str.h" #include "xbt/string.hpp" #include "xbt/utility.hpp" @@ -70,7 +71,7 @@ NetPointNs3::NetPointNs3() : ns3_node_(ns3::CreateObject(0)) stack.Install(ns3_node_); } -WifiZone::WifiZone(std::string name_, simgrid::s4u::Host* host_, ns3::Ptr ap_node_, +WifiZone::WifiZone(const std::string& name_, simgrid::s4u::Host* host_, ns3::Ptr ap_node_, ns3::Ptr channel_, int mcs_, int nss_, int network_, int link_) : name(name_) , host(host_) @@ -93,7 +94,7 @@ bool WifiZone::is_ap(ns3::Ptr node) return false; } -WifiZone* WifiZone::by_name(std::string name) +WifiZone* WifiZone::by_name(const std::string& name) { WifiZone* zone; try { @@ -174,7 +175,7 @@ static void routeCreation_cb(bool symmetrical, simgrid::kernel::routing::NetPoin std::vector const& link_list) { if (link_list.size() == 1) { - auto* link = static_cast(link_list[0]); + auto const* link = static_cast(link_list[0]); XBT_DEBUG("Route from '%s' to '%s' with link '%s' %s %s", src->get_cname(), dst->get_cname(), link->get_cname(), (link->get_sharing_policy() == simgrid::s4u::Link::SharingPolicy::WIFI ? "(wifi)" : "(wired)"), @@ -210,7 +211,24 @@ void surf_network_model_init_NS3() } static simgrid::config::Flag - ns3_tcp_model("ns3/TcpModel", "The ns-3 tcp model can be : NewReno or Reno or Tahoe", "default"); + ns3_tcp_model("ns3/TcpModel", "The ns-3 tcp model can be: NewReno or Reno or Tahoe", "default"); +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.", "", + [](std::string val) { + if (val.length() == 0) + return; + if (strcasecmp(val.c_str(), "time") == 0) { + std::srand(time(NULL)); + ns3::RngSeedManager::SetSeed(std::rand()); + ns3::RngSeedManager::SetRun(std::rand()); + } else { + int v = xbt_str_parse_int( + val.c_str(), "Invalid value for option ns3/seed. It must be either 'time', a number, or left empty."); + ns3::RngSeedManager::SetSeed(v); + ns3::RngSeedManager::SetRun(v); + } + }); namespace simgrid { namespace kernel { @@ -309,7 +327,7 @@ void NetworkNS3Model::update_actions_state(double now, double delta) ns3_socket = elm.first; SgFlow* sgFlow = elm.second; NetworkNS3Action * action = sgFlow->action_; - XBT_DEBUG("Processing socket %p (action %p)",sgFlow,action); + XBT_DEBUG("Processing flow %p (socket %s, action %p)", sgFlow, ns3_socket.c_str(), action); // Because NS3 stops as soon as a flow is finished, the other flows that ends at the same time may remains in an // inconsistent state (i.e. remains_ == 0 but finished_ == false). // However, SimGrid considers sometimes that an action with remains_ == 0 is finished. @@ -331,13 +349,13 @@ void NetworkNS3Model::update_actions_state(double now, double delta) action->last_sent_ = sgFlow->sent_bytes_; } - if(sgFlow->finished_){ + if ((sgFlow->finished_) && (remains <= 0)) { // finished_ should not become true before remains gets to 0, but it sometimes does. Let's play safe, here. socket_to_destroy.push_back(ns3_socket); - XBT_DEBUG("Destroy socket %p of action %p", ns3_socket.c_str(), action); + XBT_DEBUG("Destroy socket %s of action %p", ns3_socket.c_str(), action); action->set_remains(0); action->finish(Action::State::FINISHED); } else { - XBT_DEBUG("Socket %p sent %u bytes out of %u (%u remaining)", ns3_socket.c_str(), sgFlow->sent_bytes_, + XBT_DEBUG("Socket %s sent %u bytes out of %u (%u remaining)", ns3_socket.c_str(), sgFlow->sent_bytes_, sgFlow->total_bytes_, sgFlow->remaining_); } } @@ -347,7 +365,7 @@ void NetworkNS3Model::update_actions_state(double now, double delta) socket_to_destroy.pop_back(); SgFlow* flow = flow_from_sock.at(ns3_socket); if (XBT_LOG_ISENABLED(ns3, xbt_log_priority_debug)) { - XBT_DEBUG("Removing socket %p of action %p", ns3_socket.c_str(), flow->action_); + XBT_DEBUG("Removing socket %s of action %p", ns3_socket.c_str(), flow->action_); } delete flow; flow_from_sock.erase(ns3_socket); @@ -377,8 +395,8 @@ LinkNS3::LinkNS3(NetworkNS3Model* model, const std::string& name, double bandwid ns3::NetDeviceContainer netA; WifiZone* zone = WifiZone::by_name(name); - xbt_assert(zone != 0, "Link name '%s' does not match the 'wifi_link' property of a host.", name.c_str()); - NetPointNs3* netpoint_ns3 = zone->get_host()->get_netpoint()->extension(); + xbt_assert(zone != nullptr, "Link name '%s' does not match the 'wifi_link' property of a host.", name.c_str()); + auto* netpoint_ns3 = zone->get_host()->get_netpoint()->extension(); wifi.SetRemoteStationManager("ns3::ConstantRateWifiManager", "ControlMode", ns3::StringValue("HtMcs0"), "DataMode", ns3::StringValue("HtMcs" + std::to_string(zone->get_mcs()))); @@ -388,7 +406,8 @@ LinkNS3::LinkNS3(NetworkNS3Model* model, const std::string& name, double bandwid wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss())); wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss())); - wifiMac.SetType("ns3::ApWifiMac"); + wifiMac.SetType("ns3::ApWifiMac", + "Ssid", ns3::SsidValue(name)); netA.Add(wifi.Install(wifiPhy, wifiMac, zone->get_ap_node())); @@ -406,7 +425,7 @@ LinkNS3::LinkNS3(NetworkNS3Model* model, const std::string& name, double bandwid zone->set_network(number_of_networks); zone->set_link(number_of_links); - netpoint_ns3->ipv4_address_ = transformIpv4Address(addresses.GetAddress(addresses.GetN() - 1)); + netpoint_ns3->ipv4_address_ = transformIpv4Address(addresses.GetAddress(1)); if (number_of_links == 255) { xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255"); @@ -441,6 +460,20 @@ void LinkNS3::set_latency_profile(profile::Profile*) NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* src, s4u::Host* dst) : NetworkAction(model, *src, *dst, totalBytes, false) { + // ns-3 fails when src = dst, so avoid the problem by considering that communications are infinitely fast on the + // loopback that does not exists + if (src == dst) { + static bool warned = false; + if (not warned) { + XBT_WARN("Sending from a host %s to itself is not supported by ns-3. Every such communication finishes " + "immediately upon startup.", + src->get_cname()); + warned = true; + } + finish(Action::State::FINISHED); + return; + } + // If there is no other started actions, we need to move NS-3 forward to be sync with SimGrid if (model->get_started_action_set()->size()==1){ while(double_positive(surf_get_clock() - ns3::Simulator::Now().GetSeconds(), sg_surf_precision)){ @@ -449,9 +482,7 @@ NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* s } } - XBT_DEBUG("Communicate from %s to %s", src->get_cname(), dst->get_cname()); - - static int port_number = 1025; // Port number is limited from 1025 to 65 000 + static uint16_t port_number = 1; ns3::Ptr src_node = src->get_netpoint()->extension()->ns3_node_; ns3::Ptr dst_node = dst->get_netpoint()->extension()->ns3_node_; @@ -460,25 +491,23 @@ NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* s xbt_assert(not addr.empty(), "Element %s is unknown to ns-3. Is it connected to any one-hop link?", dst->get_netpoint()->get_cname()); - XBT_DEBUG("ns3: Create flow of %.0f Bytes from %s to %s with Interface %s", totalBytes, src->get_cname(), - dst->get_cname(), addr.c_str()); ns3::PacketSinkHelper sink("ns3::TcpSocketFactory", ns3::InetSocketAddress(ns3::Ipv4Address::GetAny(), port_number)); ns3::ApplicationContainer apps = 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()); + flow_from_sock.insert({transform_socket_ptr(sock), new SgFlow(totalBytes, this)}); sink_from_sock.insert({transform_socket_ptr(sock), apps}); sock->Bind(ns3::InetSocketAddress(port_number)); - ns3::Simulator::ScheduleNow(&start_flow, sock, addr.c_str(), port_number); - port_number++; - if(port_number > 65000){ - port_number = 1025; + port_number = 1 + (port_number % UINT16_MAX); + if (port_number == 1) XBT_WARN("Too many connections! Port number is saturated. Trying to use the oldest ports."); - } s4u::Link::on_communicate(*this); } @@ -550,14 +579,16 @@ void ns3_add_direct_route(simgrid::kernel::routing::NetPoint* src, simgrid::kern wifiPhy.Set("MaxSupportedTxSpatialStreams", ns3::UintegerValue(zone->get_nss())); wifiPhy.Set("MaxSupportedRxSpatialStreams", ns3::UintegerValue(zone->get_nss())); - wifiMac.SetType("ns3::StaWifiMac"); + wifiMac.SetType ("ns3::StaWifiMac", + "Ssid", ns3::SsidValue(link_name), + "ActiveProbing", ns3::BooleanValue(false)); netA.Add(wifi.Install(wifiPhy, wifiMac, staNode)); ns3::Config::Set("/NodeList/*/DeviceList/*/$ns3::WifiNetDevice/Phy/ChannelWidth", ns3::UintegerValue(40)); - NetPointNs3* sta_netpointNs3 = WifiZone::is_ap(host_src->ns3_node_) ? host_src : host_dst; - const char* wifi_distance = simgrid::s4u::Host::by_name(sta_netpointNs3->name_)->get_property("wifi_distance"); + simgrid::kernel::routing::NetPoint* sta_netpoint = WifiZone::is_ap(host_src->ns3_node_) ? dst : src; + const char* wifi_distance = simgrid::s4u::Host::by_name(sta_netpoint->get_name())->get_property("wifi_distance"); ns3::Ptr positionAllocS = ns3::CreateObject(); positionAllocS->Add(ns3::Vector(wifi_distance ? atof(wifi_distance) : 10.0, 0, 0)); mobility.SetPositionAllocator(positionAllocS); @@ -569,7 +600,7 @@ void ns3_add_direct_route(simgrid::kernel::routing::NetPoint* src, simgrid::kern zone->add_sta_node(); XBT_DEBUG("\tInterface stack '%s'", addr.c_str()); auto addresses = address.Assign(netA); - host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(addresses.GetN() - 1)); + host_dst->ipv4_address_ = transformIpv4Address(addresses.GetAddress(1)); } else { ns3::PointToPointHelper pointToPoint;