Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' of scm.gforge.inria.fr:/gitroot/simgrid/simgrid
authorMartin Quinson <martin.quinson@loria.fr>
Wed, 14 Sep 2011 08:33:18 +0000 (10:33 +0200)
committerMartin Quinson <martin.quinson@loria.fr>
Wed, 14 Sep 2011 08:33:18 +0000 (10:33 +0200)
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/MakeLib.cmake
buildtools/Cmake/Modules/FindNS3.cmake
src/surf/network_ns3.c
src/surf/ns3/my-point-to-point-helper.cc [new file with mode: 0644]
src/surf/ns3/my-point-to-point-helper.h [new file with mode: 0644]
src/surf/ns3/ns3_interface.cc
src/surf/ns3/ns3_interface.h
src/surf/ns3/ns3_simulator.cc
src/surf/ns3/ns3_simulator.h

index 814e0f2..62b7b4e 100644 (file)
@@ -103,6 +103,7 @@ set(EXTRA_DIST
        src/surf/network_ns3_private.h
        src/surf/ns3/ns3_interface.h
        src/surf/ns3/ns3_simulator.h
+       src/surf/ns3/my-point-to-point-helper.h
 )
 
 set(XBT_RL_SRC 
@@ -201,6 +202,18 @@ set(NS3_SRC
        src/surf/ns3/ns3_interface.cc
        src/surf/ns3/ns3_simulator.cc
        )
+       
+if(HAVE_RED_QUEUE_H)
+    set(NS3_SRC
+        ${NS3_SRC}
+        src/surf/ns3/my-point-to-point-helper.cc
+        )
+else(HAVE_RED_QUEUE_H)
+       set(EXTRA_DIST
+           ${EXTRA_DIST}
+           src/surf/ns3/my-point-to-point-helper.cc
+       )
+endif(HAVE_RED_QUEUE_H)
 
 set(SURF_SRC 
        src/surf/surf_model.c
index 3432d7f..146444f 100644 (file)
@@ -127,6 +127,11 @@ if(HAVE_NS3)
        endif(${NS3_VERSION} EQUAL 310)
 endif(HAVE_NS3)
 
+if(HAVE_NS3 AND HAVE_RED_QUEUE_H)
+           set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_HAVE_NS3_RED")
+           set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_HAVE_NS3_RED")
+endif(HAVE_NS3 AND HAVE_RED_QUEUE_H)
+
 if(HAVE_POSIX_GETTIME)
        SET(SIMGRID_DEP "${SIMGRID_DEP} -lrt")
 endif(HAVE_POSIX_GETTIME)
index b7faf9f..7b04300 100644 (file)
@@ -42,6 +42,20 @@ find_path(HAVE_CORE_MODULE_H
     ${ns3_path}
 )
 
+find_path(HAVE_RED_QUEUE_H
+       NAME ns3/red-queue.h
+    HINTS
+    $ENV{HOME}
+    PATH_SUFFIXES include ns3/include
+    PATHS
+    /opt
+    /opt/local
+    /opt/csw
+    /sw
+    /usr
+    ${ns3_path}
+)
+
 message(STATUS "Looking for core-module.h")
 if(HAVE_CORE_MODULE_H)
 message(STATUS "Looking for core-module.h - found")
@@ -50,6 +64,14 @@ message(STATUS "Looking for core-module.h - not found")
 endif(HAVE_CORE_MODULE_H)
 mark_as_advanced(HAVE_CORE_MODULE_H)
 
+message(STATUS "Looking for red-queue.h")
+if(HAVE_RED_QUEUE_H)
+message(STATUS "Looking for red-queue.h - found")
+else(HAVE_RED_QUEUE_H)
+message(STATUS "Looking for red-queue.h - not found")
+endif(HAVE_RED_QUEUE_H)
+mark_as_advanced(HAVE_RED_QUEUE_H)
+
 message(STATUS "Looking for lib ns3")
 if(HAVE_NS3_LIB)
 message(STATUS "Looking for lib ns3 - found")
@@ -103,4 +125,8 @@ if(HAVE_NS3)
        endif(NOT operation)            
 else(HAVE_NS3)
     message(STATUS "Warning: To use NS-3 Please install ns3 at least version 3.10 (http://www.nsnam.org/releases/)")
-endif(HAVE_NS3)
\ No newline at end of file
+endif(HAVE_NS3)
+
+if(HAVE_NS3 AND enable_supernovae)
+    set(enable_supernovae OFF)
+endif(HAVE_NS3 AND enable_supernovae)
\ No newline at end of file
index 898f9c2..0b56f0f 100644 (file)
@@ -216,7 +216,9 @@ void parse_ns3_add_cluster(void)
                if(host_src && host_dst){}
                else xbt_die("\tns3_add_link from %d to %d",host_src->node_num,host_dst->node_num);
 
-               ns3_add_link(host_src->node_num,host_dst->node_num,bw,lat);
+               ns3_add_link(host_src->node_num,host_src->type,
+                                        host_dst->node_num,host_dst->type,
+                                        bw,lat);
 
                free(router_id);
                free(host_id);
@@ -302,7 +304,7 @@ void create_ns3_topology()
      if(host_src && host_dst){}
      else xbt_die("\tns3_add_link from %d to %d",host_src->node_num,host_dst->node_num);
 
-     ns3_add_link(host_src->node_num,host_dst->node_num,link_bdw,link_lat);
+     ns3_add_link(host_src->node_num,host_src->type,host_dst->node_num,host_dst->type,link_bdw,link_lat);
 
      xbt_free(link_bdw);
      xbt_free(link_lat);
diff --git a/src/surf/ns3/my-point-to-point-helper.cc b/src/surf/ns3/my-point-to-point-helper.cc
new file mode 100644 (file)
index 0000000..f59149a
--- /dev/null
@@ -0,0 +1,440 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/abort.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-remote-channel.h"
+#include "ns3/queue.h"
+#include "ns3/config.h"
+#include "ns3/packet.h"
+#include "ns3/names.h"
+#include "ns3/string.h"
+#include "ns3/mpi-interface.h"
+#include "ns3/mpi-receiver.h"
+
+#include "ns3/trace-helper.h"
+#include "my-point-to-point-helper.h"
+
+NS_LOG_COMPONENT_DEFINE ("MyPointToPointHelper");
+
+///> RED Parameters  see src/node/red-queue.* for details
+//.AddAttribute ("Mode",
+//                "Whether to use Bytes (see MaxBytes) or Packets (see MaxPackets) as the maximum queue size metric.",
+//                EnumValue (BYTES), ///> currently supports BYTES only
+//                MakeEnumAccessor (&RedQueue::SetMode),
+//                MakeEnumChecker (BYTES, "Bytes",
+//                                 PACKETS, "Packets"))
+// .AddAttribute ("MaxPackets",
+//                "The maximum number of packets accepted by this RedQueue.",
+//                UintegerValue (100),
+//                MakeUintegerAccessor (&RedQueue::m_maxPackets),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("MaxBytes",
+//                "The maximum number of bytes accepted by this RedQueue.",
+//                UintegerValue (100000),
+//                MakeUintegerAccessor (&RedQueue::m_maxBytes),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("m_burst",
+//                "maximum number of m_burst packets accepted by this queue",
+//                UintegerValue (6), ///> bursts must be > minTh/avpkt
+//                MakeUintegerAccessor (&RedQueue::m_burst),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("m_avPkt",
+//                "In bytes, use with m_burst to determine the time constant for average queue size calculations",
+//                UintegerValue (1024), ///> average packet size
+//                MakeUintegerAccessor (&RedQueue::m_avPkt),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("m_minTh",
+//                "Average queue size at which marking becomes a m_prob",
+//                UintegerValue (5120), ///> in bytes  1024x5
+//                MakeUintegerAccessor (&RedQueue::m_minTh),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("m_maxTh",
+//                "Maximal marking m_prob, should be at least twice min to prevent synchronous retransmits",
+//                UintegerValue (15360), ///> in bytes 1024x15
+//                MakeUintegerAccessor (&RedQueue::m_maxTh),
+//                MakeUintegerChecker<uint32_t> ())
+// .AddAttribute ("m_rate",
+//                "this m_rate is used for calculating the average queue size after some idle time.",
+//                UintegerValue (1500000), ///> in bps, should be set to bandwidth of interface
+//                MakeUintegerAccessor (&RedQueue::m_rate),
+//                MakeUintegerChecker<uint64_t> ())
+// .AddAttribute ("m_prob",
+//                "Probability for marking, suggested values are 0.01 and 0.02",
+//                DoubleValue (0.02),
+//                MakeDoubleAccessor (&RedQueue::m_prob),
+//                MakeDoubleChecker <double> ())
+std::string qMode = "Bytes";
+std::string qBurst = "6";
+std::string qAvPkt = "1024";
+std::string qLimit = "25600"; //"100000";
+std::string qthMin = "5120";  // 1024 x 5 bytes
+std::string qthMax = "15360"; // 1024 x 15 bytes
+std::string qIdleRate = "1500000";  //1.5 Mbps
+std::string qProb = "0.02";
+
+namespace ns3 {
+
+MyPointToPointHelper::MyPointToPointHelper ()
+{
+  m_queueFactory.SetTypeId ("ns3::DropTailQueue");
+  m_queueFactory_red.SetTypeId ("ns3::RedQueue");
+//  m_queueFactory_red.Set ("Mode",    StringValue (qMode));
+//  m_queueFactory_red.Set ("MaxBytes",StringValue (qLimit));
+//  m_queueFactory_red.Set ("m_burst", StringValue (qBurst));
+//  m_queueFactory_red.Set ("m_avPkt", StringValue (qAvPkt));
+//  m_queueFactory_red.Set ("m_minTh", StringValue (qthMin));
+//  m_queueFactory_red.Set ("m_maxTh", StringValue (qthMax));
+//  m_queueFactory_red.Set ("m_rate",  StringValue (qIdleRate));
+//  m_queueFactory_red.Set ("m_prob",  StringValue (qProb));
+  m_deviceFactory.SetTypeId ("ns3::PointToPointNetDevice");
+  m_channelFactory.SetTypeId ("ns3::PointToPointChannel");
+  m_remoteChannelFactory.SetTypeId ("ns3::PointToPointRemoteChannel");
+}
+
+void 
+MyPointToPointHelper::SetQueue (std::string type,
+                              std::string n1, const AttributeValue &v1,
+                              std::string n2, const AttributeValue &v2,
+                              std::string n3, const AttributeValue &v3,
+                              std::string n4, const AttributeValue &v4,
+                              std::string n5, const AttributeValue &v5,
+                              std::string n6, const AttributeValue &v6,
+                              std::string n7, const AttributeValue &v7,
+                              std::string n8, const AttributeValue &v8)
+{
+  m_queueFactory.SetTypeId (type);
+  m_queueFactory.Set (n1, v1);
+  m_queueFactory.Set (n2, v2);
+  m_queueFactory.Set (n3, v3);
+  m_queueFactory.Set (n4, v4);
+  m_queueFactory.Set (n5, v5);
+  m_queueFactory.Set (n6, v6);
+  m_queueFactory.Set (n7, v7);
+  m_queueFactory.Set (n8, v8);
+}
+
+void 
+MyPointToPointHelper::SetDeviceAttribute (std::string n1, const AttributeValue &v1)
+{
+  m_deviceFactory.Set (n1, v1);
+}
+
+void 
+MyPointToPointHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
+{
+  m_channelFactory.Set (n1, v1);
+  m_remoteChannelFactory.Set (n1, v1);
+}
+
+void 
+MyPointToPointHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
+{
+  //
+  // All of the Pcap enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type PointToPointNetDevice.
+  //
+  Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("MyPointToPointHelper::EnablePcapInternal(): Device " << device << " not of type ns3::PointToPointNetDevice");
+      return;
+    }
+
+  PcapHelper pcapHelper;
+
+  std::string filename;
+  if (explicitFilename)
+    {
+      filename = prefix;
+    }
+  else
+    {
+      filename = pcapHelper.GetFilenameFromDevice (prefix, device);
+    }
+
+  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, 
+                                                     PcapHelper::DLT_PPP);
+  pcapHelper.HookDefaultSink<PointToPointNetDevice> (device, "PromiscSniffer", file);
+}
+
+void 
+MyPointToPointHelper::EnableAsciiInternal (
+  Ptr<OutputStreamWrapper> stream, 
+  std::string prefix, 
+  Ptr<NetDevice> nd,
+  bool explicitFilename)
+{
+  //
+  // All of the ascii enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type PointToPointNetDevice.
+  //
+  Ptr<PointToPointNetDevice> device = nd->GetObject<PointToPointNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("MyPointToPointHelper::EnableAsciiInternal(): Device " << device <<
+                   " not of type ns3::PointToPointNetDevice");
+      return;
+    }
+
+  //
+  // Our default trace sinks are going to use packet printing, so we have to 
+  // make sure that is turned on.
+  //
+  Packet::EnablePrinting ();
+
+  //
+  // If we are not provided an OutputStreamWrapper, we are expected to create 
+  // one using the usual trace filename conventions and do a Hook*WithoutContext
+  // since there will be one file per context and therefore the context would
+  // be redundant.
+  //
+  if (stream == 0)
+    {
+      //
+      // Set up an output stream object to deal with private ofstream copy 
+      // constructor and lifetime issues.  Let the helper decide the actual
+      // name of the file given the prefix.
+      //
+      AsciiTraceHelper asciiTraceHelper;
+
+      std::string filename;
+      if (explicitFilename)
+        {
+          filename = prefix;
+        }
+      else
+        {
+          filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
+        }
+
+      Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
+
+      //
+      // The MacRx trace source provides our "r" event.
+      //
+      asciiTraceHelper.HookDefaultReceiveSinkWithoutContext<PointToPointNetDevice> (device, "MacRx", theStream);
+
+      //
+      // The "+", '-', and 'd' events are driven by trace sources actually in the
+      // transmit queue.
+      //
+      Ptr<Queue> queue = device->GetQueue ();
+      asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext<Queue> (queue, "Enqueue", theStream);
+      asciiTraceHelper.HookDefaultDropSinkWithoutContext<Queue> (queue, "Drop", theStream);
+      asciiTraceHelper.HookDefaultDequeueSinkWithoutContext<Queue> (queue, "Dequeue", theStream);
+
+      // PhyRxDrop trace source for "d" event
+      asciiTraceHelper.HookDefaultDropSinkWithoutContext<PointToPointNetDevice> (device, "PhyRxDrop", theStream);
+
+      return;
+    }
+
+  //
+  // If we are provided an OutputStreamWrapper, we are expected to use it, and
+  // to providd a context.  We are free to come up with our own context if we
+  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for 
+  // compatibility and simplicity, we just use Config::Connect and let it deal
+  // with the context.
+  //
+  // Note that we are going to use the default trace sinks provided by the 
+  // ascii trace helper.  There is actually no AsciiTraceHelper in sight here,
+  // but the default trace sinks are actually publicly available static 
+  // functions that are always there waiting for just such a case.
+  //
+  uint32_t nodeid = nd->GetNode ()->GetId ();
+  uint32_t deviceid = nd->GetIfIndex ();
+  std::ostringstream oss;
+
+  oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/MacRx";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Enqueue";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Dequeue";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Drop";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/PhyRxDrop";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
+}
+
+NetDeviceContainer 
+MyPointToPointHelper::Install (NodeContainer c)
+{
+  NS_ASSERT (c.GetN () == 2);
+  return Install (c.Get (0), c.Get (1));
+}
+
+NetDeviceContainer 
+MyPointToPointHelper::Install (Ptr<Node> a, e_ns3_network_element_type_t type_a, Ptr<Node> b, e_ns3_network_element_type_t type_b)
+{
+  NetDeviceContainer container;
+  Ptr<Queue> queueA;
+  Ptr<Queue> queueB;
+
+  Ptr<PointToPointNetDevice> devA = m_deviceFactory.Create<PointToPointNetDevice> ();
+  devA->SetAddress (Mac48Address::Allocate ());
+  a->AddDevice (devA);
+
+  if(type_a == NS3_NETWORK_ELEMENT_ROUTER){
+       queueA = m_queueFactory_red.Create<Queue> ();
+  }
+  else
+         queueA = m_queueFactory.Create<Queue> ();
+  devA->SetQueue (queueA);
+
+  Ptr<PointToPointNetDevice> devB = m_deviceFactory.Create<PointToPointNetDevice> ();
+  devB->SetAddress (Mac48Address::Allocate ());
+  b->AddDevice (devB);
+
+  if(type_b == NS3_NETWORK_ELEMENT_ROUTER){
+       queueB = m_queueFactory_red.Create<Queue> ();
+  }
+  else
+         queueB = m_queueFactory.Create<Queue> ();
+  devB->SetQueue (queueB);
+
+  // If MPI is enabled, we need to see if both nodes have the same system id 
+  // (rank), and the rank is the same as this instance.  If both are true, 
+  //use a normal p2p channel, otherwise use a remote channel
+  bool useNormalChannel = true;
+  Ptr<PointToPointChannel> channel = 0;
+  if (MpiInterface::IsEnabled ())
+    {
+      uint32_t n1SystemId = a->GetSystemId ();
+      uint32_t n2SystemId = b->GetSystemId ();
+      uint32_t currSystemId = MpiInterface::GetSystemId ();
+      if (n1SystemId != currSystemId || n2SystemId != currSystemId) 
+        {
+          useNormalChannel = false;
+        }
+    }
+  if (useNormalChannel)
+    {
+      channel = m_channelFactory.Create<PointToPointChannel> ();
+    }
+  else
+    {
+      channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
+      Ptr<MpiReceiver> mpiRecA = CreateObject<MpiReceiver> ();
+      Ptr<MpiReceiver> mpiRecB = CreateObject<MpiReceiver> ();
+      mpiRecA->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devA));
+      mpiRecB->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devB));
+      devA->AggregateObject (mpiRecA);
+      devB->AggregateObject (mpiRecB);
+    }
+
+  devA->Attach (channel);
+  devB->Attach (channel);
+  container.Add (devA);
+  container.Add (devB);
+
+  return container;
+}
+
+NetDeviceContainer 
+MyPointToPointHelper::Install (Ptr<Node> a, Ptr<Node> b)
+{
+  NetDeviceContainer container;
+
+  Ptr<PointToPointNetDevice> devA = m_deviceFactory.Create<PointToPointNetDevice> ();
+  devA->SetAddress (Mac48Address::Allocate ());
+  a->AddDevice (devA);
+  Ptr<Queue> queueA = m_queueFactory.Create<Queue> ();
+  devA->SetQueue (queueA);
+  Ptr<PointToPointNetDevice> devB = m_deviceFactory.Create<PointToPointNetDevice> ();
+  devB->SetAddress (Mac48Address::Allocate ());
+  b->AddDevice (devB);
+  Ptr<Queue> queueB = m_queueFactory.Create<Queue> ();
+  devB->SetQueue (queueB);
+  // If MPI is enabled, we need to see if both nodes have the same system id
+  // (rank), and the rank is the same as this instance.  If both are true,
+  //use a normal p2p channel, otherwise use a remote channel
+  bool useNormalChannel = true;
+  Ptr<PointToPointChannel> channel = 0;
+  if (MpiInterface::IsEnabled ())
+    {
+      uint32_t n1SystemId = a->GetSystemId ();
+      uint32_t n2SystemId = b->GetSystemId ();
+      uint32_t currSystemId = MpiInterface::GetSystemId ();
+      if (n1SystemId != currSystemId || n2SystemId != currSystemId)
+        {
+          useNormalChannel = false;
+        }
+    }
+  if (useNormalChannel)
+    {
+      channel = m_channelFactory.Create<PointToPointChannel> ();
+    }
+  else
+    {
+      channel = m_remoteChannelFactory.Create<PointToPointRemoteChannel> ();
+      Ptr<MpiReceiver> mpiRecA = CreateObject<MpiReceiver> ();
+      Ptr<MpiReceiver> mpiRecB = CreateObject<MpiReceiver> ();
+      mpiRecA->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devA));
+      mpiRecB->SetReceiveCallback (MakeCallback (&PointToPointNetDevice::Receive, devB));
+      devA->AggregateObject (mpiRecA);
+      devB->AggregateObject (mpiRecB);
+    }
+
+  devA->Attach (channel);
+  devB->Attach (channel);
+  container.Add (devA);
+  container.Add (devB);
+
+  return container;
+}
+
+NetDeviceContainer
+MyPointToPointHelper::Install (Ptr<Node> a, std::string bName)
+{
+  Ptr<Node> b = Names::Find<Node> (bName);
+  return Install (a, b);
+}
+
+NetDeviceContainer 
+MyPointToPointHelper::Install (std::string aName, Ptr<Node> b)
+{
+  Ptr<Node> a = Names::Find<Node> (aName);
+  return Install (a, b);
+}
+
+NetDeviceContainer 
+MyPointToPointHelper::Install (std::string aName, std::string bName)
+{
+  Ptr<Node> a = Names::Find<Node> (aName);
+  Ptr<Node> b = Names::Find<Node> (bName);
+  return Install (a, b);
+}
+
+} // namespace ns3
diff --git a/src/surf/ns3/my-point-to-point-helper.h b/src/surf/ns3/my-point-to-point-helper.h
new file mode 100644 (file)
index 0000000..7edd931
--- /dev/null
@@ -0,0 +1,205 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef POINT_TO_POINT_HELPER_H
+#define POINT_TO_POINT_HELPER_H
+
+#include <string>
+
+#include "ns3/object-factory.h"
+#include "ns3/net-device-container.h"
+#include "ns3/node-container.h"
+#include "ns3/deprecated.h"
+
+#include "ns3/trace-helper.h"
+
+#include "ns3_interface.h"
+
+namespace ns3 {
+
+class Queue;
+class NetDevice;
+class Node;
+
+/**
+ * \brief Build a set of PointToPointNetDevice objects
+ *
+ * Normally we eschew multiple inheritance, however, the classes 
+ * PcapUserHelperForDevice and AsciiTraceUserHelperForDevice are
+ * "mixins".
+ */
+class MyPointToPointHelper : public PcapHelperForDevice, public AsciiTraceHelperForDevice
+{
+public:
+  /**
+   * Create a MyPointToPointHelper to make life easier when creating point to
+   * point networks.
+   */
+  MyPointToPointHelper ();
+  virtual ~MyPointToPointHelper () {}
+
+  /**
+   * Each point to point net device must have a queue to pass packets through.
+   * This method allows one to set the type of the queue that is automatically
+   * created when the device is created and attached to a node.
+   *
+   * \param type the type of queue
+   * \param n1 the name of the attribute to set on the queue
+   * \param v1 the value of the attribute to set on the queue
+   * \param n2 the name of the attribute to set on the queue
+   * \param v2 the value of the attribute to set on the queue
+   * \param n3 the name of the attribute to set on the queue
+   * \param v3 the value of the attribute to set on the queue
+   * \param n4 the name of the attribute to set on the queue
+   * \param v4 the value of the attribute to set on the queue
+   *
+   * Set the type of queue to create and associated to each
+   * PointToPointNetDevice created through MyPointToPointHelper::Install.
+   */
+  void SetQueue (std::string type,
+                 std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+                 std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+                 std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+                 std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
+                 std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
+                 std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
+                 std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue (),
+                 std::string n8 = "", const AttributeValue &v8 = EmptyAttributeValue ());
+
+  /**
+   * Set an attribute value to be propagated to each NetDevice created by the
+   * helper.
+   *
+   * \param name the name of the attribute to set
+   * \param value the value of the attribute to set
+   *
+   * Set these attributes on each ns3::PointToPointNetDevice created
+   * by MyPointToPointHelper::Install
+   */
+  void SetDeviceAttribute (std::string name, const AttributeValue &value);
+
+  /**
+   * Set an attribute value to be propagated to each Channel created by the
+   * helper.
+   *
+   * \param name the name of the attribute to set
+   * \param value the value of the attribute to set
+   *
+   * Set these attribute on each ns3::PointToPointChannel created
+   * by MyPointToPointHelper::Install
+   */
+  void SetChannelAttribute (std::string name, const AttributeValue &value);
+
+  /**
+   * \param c a set of nodes
+   *
+   * This method creates a ns3::PointToPointChannel with the
+   * attributes configured by MyPointToPointHelper::SetChannelAttribute,
+   * then, for each node in the input container, we create a 
+   * ns3::PointToPointNetDevice with the requested attributes, 
+   * a queue for this ns3::NetDevice, and associate the resulting 
+   * ns3::NetDevice with the ns3::Node and ns3::PointToPointChannel.
+   */
+  NetDeviceContainer Install (NodeContainer c);
+
+  /**
+   * \param a first node
+   * \param b second node
+   *
+   * Saves you from having to construct a temporary NodeContainer. 
+   * Also, if MPI is enabled, for distributed simulations, 
+   * appropriate remote point-to-point channels are created.
+   */
+  NetDeviceContainer Install (Ptr<Node> a, Ptr<Node> b);
+
+  /**
+   * \param a first node
+   * \param b second node
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   * Also, if MPI is enabled, for distributed simulations,
+   * appropriate remote point-to-point channels are created.
+   */
+  NetDeviceContainer Install (Ptr<Node> a, e_ns3_network_element_type_t type_a, Ptr<Node> b, e_ns3_network_element_type_t type_b);
+
+  /**
+   * \param a first node
+   * \param bName name of second node
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   */
+  NetDeviceContainer Install (Ptr<Node> a, std::string bName);
+
+  /**
+   * \param aName Name of first node
+   * \param b second node
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   */
+  NetDeviceContainer Install (std::string aName, Ptr<Node> b);
+
+  /**
+   * \param aNode Name of first node
+   * \param bNode Name of second node
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   */
+  NetDeviceContainer Install (std::string aNode, std::string bNode);
+
+private:
+  /**
+   * \brief Enable pcap output the indicated net device.
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * \param prefix Filename prefix to use for pcap files.
+   * \param nd Net device for which you want to enable tracing.
+   * \param promiscuous If true capture all possible packets available at the device.
+   * \param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  virtual void EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename);
+
+  /**
+   * \brief Enable ascii trace output on the indicated net device.
+   * \internal
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * \param stream The output stream object to use when logging ascii traces.
+   * \param prefix Filename prefix to use for ascii trace files.
+   * \param nd Net device for which you want to enable tracing.
+   */
+  virtual void EnableAsciiInternal (
+    Ptr<OutputStreamWrapper> stream,
+    std::string prefix,
+    Ptr<NetDevice> nd,
+    bool explicitFilename);
+
+  ObjectFactory m_queueFactory;
+  ObjectFactory m_queueFactory_red;
+  ObjectFactory m_channelFactory;
+  ObjectFactory m_remoteChannelFactory;
+  ObjectFactory m_deviceFactory;
+};
+
+} // namespace ns3
+
+#endif /* POINT_TO_POINT_HELPER_H */
index a748ce3..eed590c 100644 (file)
@@ -10,6 +10,7 @@
 #include "xbt/log.h"
 #include "xbt/dynar.h"
 
+
 using namespace ns3;
 
 extern xbt_lib_t host_lib;
@@ -24,8 +25,6 @@ NodeContainer nodes;
 NodeContainer Cluster_nodes;
 Ipv4InterfaceContainer interfaces;
 
-
-
 int number_of_nodes = 0;
 int number_of_clusters_nodes = 0;
 int number_of_links = 1;
@@ -103,6 +102,9 @@ int ns3_initialize(const char* TcpProtocol){
   Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1024)); // 1024-byte packet for easier reading
   Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1));
 
+#ifdef _HAVE_NS3_RED
+  XBT_INFO("Using RED version of ns3");
+#endif
   if(!strcmp(TcpProtocol,"default")){
          return 0;
   }
@@ -227,14 +229,20 @@ static char* transformIpv4Address (Ipv4Address from){
                return IPaddr;
 }
 
-void * ns3_add_link(int src,int dst,char * bw,char * lat)
+void * ns3_add_link(int src, e_ns3_network_element_type_t type_src,
+                                       int dst, e_ns3_network_element_type_t type_dst,
+                                       char * bw,char * lat)
 {
        if(number_of_links == 1 ) {
                LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
                LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
        }
 
+#ifdef _HAVE_NS3_RED
+       MyPointToPointHelper pointToPoint;
+#else
        PointToPointHelper pointToPoint;
+#endif
        NetDeviceContainer netA;
        Ipv4AddressHelper address;
 
@@ -246,7 +254,11 @@ void * ns3_add_link(int src,int dst,char * bw,char * lat)
        pointToPoint.SetChannelAttribute ("Delay", StringValue (lat));
        //pointToPoint.EnablePcapAll("test_ns3_trace"); //DEBUG
 
+#ifdef _HAVE_NS3_RED
+       netA.Add(pointToPoint.Install (a, type_src, b, type_dst));
+#else
        netA.Add(pointToPoint.Install (a, b));
+#endif
 
        char * adr = bprintf("%d.%d.0.0",number_of_networks,number_of_links);
        address.SetBase (adr, "255.255.0.0");
index 1eb29ea..15f847d 100644 (file)
@@ -42,7 +42,9 @@ XBT_PUBLIC(void *) ns3_add_host(char * id);
 XBT_PUBLIC(void *) ns3_add_host_cluster(char * id);
 XBT_PUBLIC(void *) ns3_add_router(char * id);
 XBT_PUBLIC(void *) ns3_add_AS(char * id);
-XBT_PUBLIC(void *) ns3_add_link(int src,int dst,char * bw,char * lat);
+XBT_PUBLIC(void *) ns3_add_link(int src, e_ns3_network_element_type_t type_src,
+                                                               int dst, e_ns3_network_element_type_t type_dst,
+                                                               char * bw,char * lat);
 XBT_PUBLIC(void *) ns3_end_platform(void);
 XBT_PUBLIC(void *) ns3_add_cluster(char * bw,char * lat,char *id);
 #ifdef __cplusplus
index 07abf0c..7c62e05 100644 (file)
@@ -110,28 +110,29 @@ static void receive_callback(Ptr<Socket> localSocket){
 }
 
 static void send_callback(Ptr<Socket> localSocket, uint32_t txSpace){
+       uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*txSpace);
        MySocket* mysocket = (MySocket*)xbt_dict_get_or_null(dict_socket,(char*)&localSocket);
-
        if (mysocket->remaining == 0){
-         //all data was already buffered (and socket was already closed), just return
-         return;
+                 //all data was already buffered (and socket was already closed), just return
+                 return;
        }
-
-       uint32_t toWrite = min (mysocket->remaining, txSpace);
-       uint8_t *data = (uint8_t*)malloc(sizeof(uint8_t)*toWrite);
-       int amountSent = localSocket->Send (&data[0], toWrite, 0);
-       free (data);
-       if (amountSent > 0){
-         mysocket->bufferedBytes += amountSent;
-         mysocket->remaining -= amountSent;
+       while (mysocket->sentBytes < mysocket->totalBytes
+                       && localSocket->GetTxAvailable () > 0)
+       {
+      uint32_t toWrite = min ((mysocket->remaining), txSpace);
+      toWrite = min (toWrite, localSocket->GetTxAvailable ());
+      int amountSent = localSocket->Send (&data[0], toWrite, 0);
+
+      if(amountSent < 0)
+         return;
+         (mysocket->sentBytes) += amountSent;
+         (mysocket->remaining) -= amountSent;
+      XBT_DEBUG("send_cb of F[%p, %p, %d] (%d/%d) %d buffered", mysocket, mysocket->action, mysocket->totalBytes, mysocket->remaining, mysocket->totalBytes, amountSent);
+
+    }
+       if ((mysocket->sentBytes) >= mysocket->totalBytes){
+               localSocket->Close();
        }
-  XBT_DEBUG("send_cb of F[%p, %p, %d] (%d/%d) %d buffered", mysocket, mysocket->action, mysocket->totalBytes, mysocket->remaining, mysocket->totalBytes, amountSent);
-
-  if (mysocket->remaining == 0){
-    //everything was buffered to send, tell NS3 to close the socket
-    localSocket->Close();
-  }
-       return;
 }
 
 static void datasent_callback(Ptr<Socket> localSocket, uint32_t dataSent){
index 4f91f1a..503a7d5 100644 (file)
@@ -10,6 +10,9 @@
 #ifdef __cplusplus
 
 #include "ns3/core-module.h"
+#ifdef _HAVE_NS3_RED
+#include "my-point-to-point-helper.h"
+#endif
 
 #ifdef _NS3_3_10
        /*NS3 3.10*/
@@ -29,6 +32,7 @@
        #include "ns3/point-to-point-helper.h"
        #include "ns3/packet-sink-helper.h"
        #include "ns3/inet-socket-address.h"
+       #include "ns3/tcp-socket-factory.h"
 #endif
 
 using namespace ns3;