+
+void ns3_simulator(double maxSeconds)
+{
+ if (maxSeconds > 0.0) // If there is a maximum amount of time to run
+ ns3::Simulator::Stop(ns3::Seconds(maxSeconds));
+ XBT_DEBUG("Start simulator for at most %fs (current time: %f)", maxSeconds, surf_get_clock());
+ ns3::Simulator::Run ();
+}
+
+void ns3_create_flow(simgrid::s4u::Host* src, simgrid::s4u::Host* dst,
+ u_int32_t TotalBytes,
+ simgrid::surf::NetworkNS3Action* action) {
+ unsigned int node1 = src->pimpl_netpoint->extension<NetPointNs3>()->node_num;
+ unsigned int node2 = dst->pimpl_netpoint->extension<NetPointNs3>()->node_num;
+
+ ns3::Ptr<ns3::Node> src_node = nodes.Get(node1);
+ ns3::Ptr<ns3::Node> dst_node = nodes.Get(node2);
+
+ xbt_assert(node2 < IPV4addr.size(), "Element %s is unknown to NS3. Is it connected to any one-hop link?",
+ dst->pimpl_netpoint->getCname());
+ std::string& addr = IPV4addr[node2];
+ xbt_assert(not addr.empty(), "Element %s is unknown to NS3. Is it connected to any one-hop link?",
+ dst->pimpl_netpoint->getCname());
+
+ XBT_DEBUG("ns3_create_flow %u 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::Ptr<ns3::Socket> sock = ns3::Socket::CreateSocket(src_node, ns3::TcpSocketFactory::GetTypeId());
+
+ flowFromSock.insert({transformSocketPtr(sock), new SgFlow(TotalBytes, action)});
+
+ sock->Bind(ns3::InetSocketAddress(port_number));
+
+ ns3::Simulator::ScheduleNow(&StartFlow, sock, addr.c_str(), port_number);
+
+ port_number++;
+ xbt_assert(port_number <= 65000, "Too many connections! Port number is saturated.");
+}
+
+// initialize the NS3 interface and environment
+void ns3_initialize(const char* TcpProtocol){
+// tcpModel are:
+// "ns3::TcpNewReno"
+// "ns3::TcpReno"
+// "ns3::TcpTahoe"
+
+ 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 (not strcmp(TcpProtocol, "default"))
+ return;
+
+ if (not strcmp(TcpProtocol, "Reno")) {
+ XBT_INFO("Switching Tcp protocol to '%s'",TcpProtocol);
+ ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpReno"));
+ return;
+ }
+ if (not strcmp(TcpProtocol, "NewReno")) {
+ XBT_INFO("Switching Tcp protocol to '%s'",TcpProtocol);
+ ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpNewReno"));
+ return;
+ }
+ if (not strcmp(TcpProtocol, "Tahoe")) {
+ XBT_INFO("Switching Tcp protocol to '%s'",TcpProtocol);
+ ns3::Config::SetDefault ("ns3::TcpL4Protocol::SocketType", ns3::StringValue("ns3::TcpTahoe"));
+ return;
+ }
+
+ xbt_die("The ns3/TcpModel must be : NewReno or Reno or Tahoe");
+}
+
+void ns3_add_cluster(const char* id, double bw, double lat) {
+ ns3::NodeContainer Nodes;
+
+ for (unsigned int i = number_of_clusters_nodes; i < Cluster_nodes.GetN(); i++) {
+ Nodes.Add(Cluster_nodes.Get(i));
+ XBT_DEBUG("Add node %u to cluster", i);
+ }
+ number_of_clusters_nodes = Cluster_nodes.GetN();
+
+ XBT_DEBUG("Add router %u to cluster", nodes.GetN() - Nodes.GetN() - 1);
+ Nodes.Add(nodes.Get(nodes.GetN()-Nodes.GetN()-1));
+
+ xbt_assert(Nodes.GetN() <= 65000, "Cluster with NS3 is limited to 65000 nodes");
+ ns3::CsmaHelper csma;
+ csma.SetDeviceAttribute("DataRate", ns3::DataRateValue(ns3::DataRate(bw*8)));// NS3 takes bps, but we provide Bps
+ csma.SetChannelAttribute("Delay", ns3::TimeValue(ns3::Seconds(lat)));
+ ns3::NetDeviceContainer devices = csma.Install(Nodes);
+ XBT_DEBUG("Create CSMA");
+
+ std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
+ XBT_DEBUG("Assign IP Addresses %s to CSMA.", addr.c_str());
+ ns3::Ipv4AddressHelper ipv4;
+ ipv4.SetBase(addr.c_str(), "255.255.0.0");
+ interfaces.Add(ipv4.Assign (devices));
+
+ if(number_of_links == 255){
+ xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
+ number_of_links = 1;
+ number_of_networks++;
+ }else{
+ number_of_links++;
+ }
+ XBT_DEBUG("Number of nodes in Cluster_nodes: %u", Cluster_nodes.GetN());
+}
+
+static std::string transformIpv4Address(ns3::Ipv4Address from)
+{
+ std::stringstream sstream;
+ sstream << from ;
+ return sstream.str();
+}
+
+void ns3_add_link(NetPointNs3* src, NetPointNs3* dst, double bw, double lat) {
+ ns3::PointToPointHelper pointToPoint;
+
+ ns3::Ipv4AddressHelper address;
+
+ int srcNum = src->node_num;
+ int dstNum = dst->node_num;
+
+ ns3::Ptr<ns3::Node> a = nodes.Get(srcNum);
+ ns3::Ptr<ns3::Node> b = nodes.Get(dstNum);
+
+ XBT_DEBUG("\tAdd PTP from %d to %d bw:'%f Bps' lat:'%fs'", srcNum, dstNum, bw, lat);
+ pointToPoint.SetDeviceAttribute("DataRate", ns3::DataRateValue(ns3::DataRate(bw*8)));// NS3 takes bps, but we provide Bps
+ pointToPoint.SetChannelAttribute("Delay", ns3::TimeValue(ns3::Seconds(lat)));
+
+ std::string filename = simgrid::xbt::string_printf("link-%d-%d.tr", srcNum, dstNum);
+ ns3::AsciiTraceHelper ascii;
+ pointToPoint.EnableAsciiAll(ascii.CreateFileStream(filename));
+ pointToPoint.EnablePcapAll ("tcp-bulk-send", false);
+
+ ns3::NetDeviceContainer netA;
+ netA.Add(pointToPoint.Install (a, b));
+
+ std::string addr = simgrid::xbt::string_printf("%d.%d.0.0", number_of_networks, number_of_links);
+ address.SetBase(addr.c_str(), "255.255.0.0");
+ XBT_DEBUG("\tInterface stack '%s'", addr.c_str());
+ interfaces.Add(address.Assign (netA));
+
+ if (IPV4addr.size() <= (unsigned)srcNum)
+ IPV4addr.resize(srcNum + 1);
+ IPV4addr[srcNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 2));
+
+ if (IPV4addr.size() <= (unsigned)dstNum)
+ IPV4addr.resize(dstNum + 1);
+ IPV4addr[dstNum] = transformIpv4Address(interfaces.GetAddress(interfaces.GetN() - 1));
+
+ if (number_of_links == 255){
+ xbt_assert(number_of_networks < 255, "Number of links and networks exceed 255*255");
+ number_of_links = 1;
+ number_of_networks++;
+ } else {
+ number_of_links++;
+ }
+}