X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/b6d559f77513404532d4379b227cd773bbbfef72..53f36dc53dfef67528460488c6d8ee3913153968:/src/surf/network_ns3.cpp diff --git a/src/surf/network_ns3.cpp b/src/surf/network_ns3.cpp index 933b4df7f7..741622330a 100644 --- a/src/surf/network_ns3.cpp +++ b/src/surf/network_ns3.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "network_ns3.hpp" #include "ns3/ns3_simulator.hpp" @@ -39,6 +40,7 @@ std::vector IPV4addr; *****************/ extern std::map flow_from_sock; +extern std::map sink_from_sock; static ns3::InternetStackHelper stack; static ns3::NodeContainer nodes; @@ -190,34 +192,22 @@ Action* NetworkNS3Model::communicate(s4u::Host* src, s4u::Host* dst, double size double NetworkNS3Model::next_occuring_event(double now) { - double time_to_next_flow_completion; + double time_to_next_flow_completion = 0.0; XBT_DEBUG("ns3_next_occuring_event"); //get the first relevant value from the running_actions list if (get_started_action_set()->empty() || now == 0.0) return -1.0; - bool ns3_processed_all_finished_flows; - do { - double delta = surf_get_clock() + now - ns3::Simulator::Now().GetSeconds(); - ns3_simulator(delta); - time_to_next_flow_completion = ns3::Simulator::Now().GetSeconds() - surf_get_clock(); - - // NS3 stops as soon as it detects that a flow is finished. - // However, to stop NS3 in a consistant state for the current simulated time, - // we need to make sure that NS3 detects all the flows finishing at the current time. - ns3_processed_all_finished_flows = true; - // A flow that has 0 remaining_ is finishing at the current simulated time. - // However, NS3 hadn't notice it yet if finished_ == false. - for (const auto& elm : flow_from_sock) { - SgFlow* sgFlow = elm.second; - if(!sgFlow->finished_ && sgFlow->remaining_ == 0){ - ns3_processed_all_finished_flows = false; - break; - } - } - } while (!ns3_processed_all_finished_flows || double_equals(time_to_next_flow_completion, 0, sg_surf_precision)); - + XBT_DEBUG("doing a ns3 simulation for a duration of %f", now); + ns3_simulator(now); + time_to_next_flow_completion = ns3::Simulator::Now().GetSeconds() - surf_get_clock(); + // NS-3 stops as soon as a flow ends, + // but it does not process the other flows that may finish at the same (simulated) time. + // If another flow ends at the same time, time_to_next_flow_completion = 0 + if(double_equals(time_to_next_flow_completion, 0, sg_surf_precision)) + time_to_next_flow_completion = 0.0; + XBT_DEBUG("min : %f", now); XBT_DEBUG("ns3 time : %f", ns3::Simulator::Now().GetSeconds()); XBT_DEBUG("surf time : %f", surf_get_clock()); @@ -245,7 +235,13 @@ void NetworkNS3Model::update_actions_state(double now, double delta) SgFlow* sgFlow = elm.second; NetworkNS3Action * action = sgFlow->action_; XBT_DEBUG("Processing socket %p (action %p)",sgFlow,action); - action->set_remains(action->get_cost() - sgFlow->sent_bytes_); + // Because NS3 stops as soon as a flow is finished, the other flows that ends at the same time may remains in an inconsistant state + // (i.e. remains_ == 0 but finished_ == false). + // However, SimGrid considers sometimes that an action with remains_ == 0 is finished. + // Thus, to avoid inconsistencies between SimGrid and NS3, set remains to 0 only when the flow is finished in NS3 + int remains = action->get_cost() - sgFlow->sent_bytes_; + if(remains > 0) + action->set_remains(remains); if (TRACE_is_enabled() && action->get_state() == kernel::resource::Action::State::STARTED) { double data_delta_sent = sgFlow->sent_bytes_ - action->last_sent_; @@ -263,6 +259,7 @@ void NetworkNS3Model::update_actions_state(double now, double delta) if(sgFlow->finished_){ socket_to_destroy.push_back(ns3_socket); XBT_DEBUG("Destroy socket %p of action %p", ns3_socket.c_str(), action); + action->set_remains(0); action->finish(kernel::resource::Action::State::FINISHED); } else { XBT_DEBUG("Socket %p sent %u bytes out of %u (%u remaining)", ns3_socket.c_str(), sgFlow->sent_bytes_, @@ -279,6 +276,7 @@ void NetworkNS3Model::update_actions_state(double now, double delta) } delete flow; flow_from_sock.erase(ns3_socket); + sink_from_sock.erase(ns3_socket); } } @@ -335,17 +333,22 @@ NetworkNS3Action::NetworkNS3Action(Model* model, double totalBytes, s4u::Host* s XBT_DEBUG("ns3: Create flow of %.0f Bytes from %u to %u with Interface %s", totalBytes, node1, node2, addr.c_str()); ns3::PacketSinkHelper sink("ns3::TcpSocketFactory", ns3::InetSocketAddress(ns3::Ipv4Address::GetAny(), port_number)); - sink.Install(dst_node); + ns3::ApplicationContainer apps = sink.Install(dst_node); ns3::Ptr sock = ns3::Socket::CreateSocket(src_node, ns3::TcpSocketFactory::GetTypeId()); 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; + XBT_WARN("Too many connections! Port number is saturated. Trying to use the oldest ports."); + } xbt_assert(port_number <= 65000, "Too many connections! Port number is saturated."); s4u::Link::on_communicate(*this, src, dst);