merge with trunk
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 13 May 2007 11:24:28 +0200
changeset 593 90cf12cb4ab7
parent 592 f7e4beac3e31 (current diff)
parent 541 4dab7168be35 (diff)
child 594 bf1c6a6ab58d
merge with trunk
examples/simple-p2p.cc
src/devices/p2p-gfr/p2p-channel.cc
src/devices/p2p-gfr/p2p-channel.h
src/devices/p2p-gfr/p2p-net-device.cc
src/devices/p2p-gfr/p2p-net-device.h
src/devices/p2p/p2p-topology.cc
src/devices/p2p/p2p-topology.h
src/internet-node/i-ipv4-impl.cc
src/internet-node/i-ipv4-impl.h
src/node/application.h
src/node/i-ipv4.h
--- a/.hgignore	Sun May 13 10:57:43 2007 +0200
+++ b/.hgignore	Sun May 13 11:24:28 2007 +0200
@@ -2,6 +2,8 @@
 .*\.o$
 .*~$
 build-dir
+build
 .*\.sconsign
 doc/html.*
 doc/latex.*
+.lock-wscript
--- a/doc/main.txt	Sun May 13 10:57:43 2007 +0200
+++ b/doc/main.txt	Sun May 13 11:24:28 2007 +0200
@@ -19,6 +19,7 @@
  *    - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager
  *    - debugging facilities: \ref debugging, \ref assert, \ref error
  *    - \ref randomvariable
+ *    - \ref config
  *    - a class to handle automatic deletion of multiple sets of objects of different types: 
  *      ns3::ObjectContainer
  *
--- a/examples/simple-p2p.cc	Sun May 13 10:57:43 2007 +0200
+++ b/examples/simple-p2p.cc	Sun May 13 11:24:28 2007 +0200
@@ -66,7 +66,6 @@
 #include "ns3/trace-root.h"
 #include "ns3/p2p-topology.h"
 #include "ns3/onoff-application.h"
-#include "ns3/application-list.h"
 #include "ns3/random-variable.h"
 
 using namespace ns3;
@@ -132,6 +131,15 @@
       channel2, n2, Ipv4Address("10.1.3.1"),
       n3, Ipv4Address("10.1.3.2"));
 
+  // Finally, we add static routes.  These three steps (Channel and
+  // NetDevice creation, IP Address assignment, and routing) are 
+  // separated because there may be a need to postpone IP Address
+  // assignment (emulation) or modify to use dynamic routing
+  PointToPointTopology::AddIpv4Routes(n0, n2, channel0);
+  PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
+  PointToPointTopology::AddIpv4Routes(n2, n3, channel2);
+
+
   // Create the OnOff application to send UDP datagrams of size
   // 210 bytes at a rate of 448 Kb/s
   Ptr<OnOffApplication> ooff = MakeNewObject<OnOffApplication> (
@@ -175,7 +183,8 @@
 
   // Also configure some tcpdump traces; each interface will be traced
   // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
-  // and can be read by the "tcpdump -r" command
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
   PcapTrace pcaptrace ("simple-p2p.pcap");
   pcaptrace.TraceAllIp ();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ns3/_placeholder_	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,1 @@
+This is a placeholder file used only to keep the ns3 directory present (needed for the WAF build system).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,30 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import Params
+
+def build(bld):
+    def create_ns_prog(name, source, deps=['core', 'common', 'simulator']):
+        obj = bld.create_obj('cpp', 'program')
+        obj.target = name
+        obj.uselib_local = ' '.join(["ns3-%s" % dep for dep in deps])
+        obj.source = source
+        for module in deps:
+            obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,))
+        return obj
+        
+    obj = create_ns_prog('main-callback', 'main-callback.cc')
+    obj = create_ns_prog('main-simulator', 'main-simulator.cc')
+    obj = create_ns_prog('main-packet', 'main-packet.cc')
+    #obj = create_ns_prog('main-trace', 'main-trace.cc')
+    obj = create_ns_prog('main-test', 'main-test.cc')
+    obj = create_ns_prog('main-ptr', 'main-ptr.cc')
+
+    #obj = create_ns_prog('main-p2p-net-device-if', 'main-p2p-net-device-if.cc',
+    #                     deps=['core', 'common', 'simulator', 'node', 'p2p'])
+
+    obj = create_ns_prog('main-simple', 'main-simple.cc',
+                         deps=['core', 'common', 'simulator',
+                               'node', 'internet-node', 'applications'])
+
+    #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc',
+    #                     deps=['core', 'common', 'simulator', 'node', 'p2p'])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/applications/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,20 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    obj = bld.create_obj('cpp', 'shlib')
+    obj.name = 'ns3-applications'
+    obj.target = obj.name
+    obj.deps = ['ns3-node']
+    obj.source = [
+        'application-list.cc',
+        'application.cc',
+        'onoff-application.cc',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'application-list.h',
+        'application.h',
+        'onoff-application.h',
+        ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,49 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    common = bld.create_obj('cpp', 'shlib')
+    common.name = 'ns3-common'
+    common.target = common.name
+    common.deps = ['ns3-core', 'ns3-simulator']
+    common.source = [
+        'buffer.cc',
+        'header.cc',
+        'chunk.cc',
+        'trailer.cc',
+        'packet.cc',
+        'tags.cc',
+        'pcap-writer.cc',
+        'variable-tracer-test.cc',
+        'trace-context.cc',
+        'trace-resolver.cc',
+        'callback-trace-source.cc',
+        'empty-trace-resolver.cc',
+        'composite-trace-resolver.cc',
+        'trace-root.cc',
+        'data-rate.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'buffer.h',
+        'header.h',
+        'chunk.h',
+        'trailer.h',
+        'tags.h',
+        'packet.h',
+        'uv-trace-source.h',
+        'sv-trace-source.h',
+        'fv-trace-source.h',
+        'pcap-writer.h',
+        'callback-trace-source.h',
+        'trace-context.h',
+        'trace-resolver.h',
+        'empty-trace-resolver.h',
+        'composite-trace-resolver.h',
+        'array-trace-resolver.h',
+        'trace-root.h',
+        'terminal-trace-resolver.h',
+        'smartvector.h',
+        'smartset.h',
+        'data-rate.h',
+        ]
--- a/src/core/command-line.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/core/command-line.h	Sun May 13 11:24:28 2007 +0200
@@ -8,16 +8,48 @@
 
 namespace ns3 {
 
+/**
+ * \brief Command line argument processing class
+ * \ingroup config
+ *
+ * Often times in simulations, the user will want the ability to change and
+ * tweak simulation parameters without having to recompile the entire 
+ * simulation.  This can be done by passing arguments in from the command
+ * line invocation of a simulation.
+ * This class is a collection of static functions to aid in this facility.
+ * By using it, users get the automatic things like support for --help command
+ * line arguments.  See samples/main-default-value.cc for more info.
+ */
 class CommandLine
 {
 public:
+  /**
+   * \brief Add a command line argument to the system
+   * \param name Name of the string to expect on the command line
+   * \param help A help string for this param, displayed --help is used.
+   * \param value The desination to store the value read from the command line
+   */
   template <typename T>
   static void AddArgValue (const std::string &name,
 			   const std::string &help, 
 			   T &value);
+  /**
+   * \brief Add a command line triggered function call to the system
+   * \param name Name of the string to expect on the command line
+   * \param help A help string for this param, displayed --help is used.
+   * \param value An ns3::Callback that gets called if name is present as a
+   * commandline argument.
+   */
   static void AddArgCommand (const std::string &name,
 			     const std::string &help,
 			     Callback<void> cb);
+  /**
+   * \brief Parse the command line for arguments thus far added
+   * \param argc Number of strings on the command line; pass this directly from
+   * the first argument of your main(int,char**) function 
+   * \param argv Array of strings passed in as arguments; pass this directly from
+   * the second argument of your main(int,char**) function
+   */
   static void Parse (int argc, char *argv[]);
  private:
   template <typename T>
--- a/src/core/default-value.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/core/default-value.h	Sun May 13 11:24:28 2007 +0200
@@ -6,6 +6,11 @@
 #include <list>
 #include "callback.h"
 
+/**
+ * \defgroup config Simulation configuration
+ *
+ */
+
 namespace ns3 {
 
 class DefaultValueBase
@@ -45,6 +50,7 @@
 };
 
 /**
+ * \ingroup config
  * \param name name of variable to bind
  * \param value value to bind to the specified variable
  *
@@ -58,6 +64,7 @@
 
 /**
  * \brief A Boolean variable for ns3::Bind
+ * \ingroup config
  *
  * Every instance of this type is automatically 
  * registered in the variable pool which is used
@@ -95,6 +102,7 @@
 
 /**
  * \brief An Integer variable for ns3::Bind
+ * \ingroup config
  *
  * Every instance of this type is automatically 
  * registered in the variable pool which is used
@@ -147,6 +155,14 @@
   T m_value;
 };
 
+/**
+ * \brief Named enumeration defaults
+ * \ingroup config
+ *
+ * Every instance of this type is automatically 
+ * registered in the variable pool which is used
+ * by ns3::Bind. 
+ */
 class StringEnumDefaultValue : public DefaultValueBase
 {
 public:
@@ -168,6 +184,7 @@
 
 /**
  * \brief An enum variable for ns3::Bind
+ * \ingroup config
  *
  * Every instance of this type is automatically 
  * registered in the variable pool which is used
@@ -232,6 +249,11 @@
   T m_value;
 };
 
+/**
+ * \brief Class used to call a certain function during the configuration of the
+ * simulation
+ * \ingroup config
+ */
 class CommandDefaultValue : public DefaultValueBase
 {
 public:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,74 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import sys
+
+
+def configure(conf):
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'stdlib.h'
+    e.define = 'HAVE_STDLIB_H'
+    e.run()
+
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'stdlib.h'
+    e.define = 'HAVE_GETENV'
+    e.run()
+
+    conf.write_config_header('ns3/core-config.h')
+
+
+
+def build(bld):
+    core = bld.create_obj('cpp', 'shlib')
+    core.name = 'ns3-core'
+    core.target = core.name
+    core.deps = 'ns3-core-headers'
+    core.source = [
+        'reference-list-test.cc',
+        'callback-test.cc',
+        'debug.cc',
+        'assert.cc',
+        'ptr.cc',
+        'object.cc',
+        'test.cc',
+        'random-variable.cc',
+        'rng-stream.cc',
+        'ns-unknown.cc',
+        'uid-manager.cc',
+        'default-value.cc',
+        'command-line.cc',
+        'type-name.cc',
+        'ns-unknown-manager.cc',
+        ]
+
+    if sys.platform == 'win32':
+        core.source.extend([
+            'win32-system-wall-clock-ms.cc',
+            ])
+    else:
+        core.source.extend([
+            'unix-system-wall-clock-ms.cc',
+            ])
+    
+    headers = bld.create_obj('ns3header')
+    headers.name = 'ns3-core-headers'
+    headers.source = [
+        'system-wall-clock-ms.h',
+        'reference-list.h',
+        'callback.h',
+        'ptr.h',
+        'object.h',
+        'debug.h',
+        'assert.h',
+        'fatal-error.h',
+        'test.h',
+        'random-variable.h',
+        'rng-stream.h',
+        'ns-unknown.h',
+        'default-value.h',
+        'command-line.h',
+        'type-name.h',
+        'ns-unknown-manager.h',
+        ]
+
--- a/src/devices/p2p-gfr/p2p-channel.cc	Sun May 13 10:57:43 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,98 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Implementation of simple point-to-point channel
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ns3/simulator.h"
-#include "ns3/packet.h"
-#include "ns3/node.h"
-#include "p2p-channel.h"
-#include "p2p-net-device.h"
-
-namespace ns3 {
-
-P2PChannel::P2PChannel(const Time& delay, double maxRate) 
-  : m_nd1(0), m_nd2(0),
-    m_delay (delay),
-    m_maxRate (maxRate)
-{
-}
-
-P2PChannel::~P2PChannel ()
-{}
-
-// Channels create compatible net devices
-P2PNetDevice* P2PChannel::CreateNetDevice(Node *node, MacAddress address)
-{
-  // Create a new point-to-point network device
-  P2PNetDevice* nd = new P2PNetDevice(node, address);
-  nd->Connect (this);
-  // Add to list of peers
-  if (!m_nd1) m_nd1 = nd;
-  else m_nd2 = nd;
-  return nd;
-}
-
-void P2PChannel::RemoveNetDevice(NetDevice* nd)
-{
-  if (nd == m_nd1) m_nd1 = 0;
-  if (nd == m_nd2) m_nd2 = 0;
-  // Now if all removed, remove the channel as well
-  if (!m_nd1 && !m_nd2)
-    {
-      delete this;
-    }
-}
-
-void P2PChannel::Send(P2PNetDevice *device, Packet& p, double rate)
-{ // Schedule a receive event at receiver
-  // First calculate time in future
-  double maxRate;
-  if (rate < m_maxRate)
-    {
-      maxRate = rate;
-    } 
-  else
-    {
-      maxRate = m_maxRate;
-    }
-  Time txTime = Seconds (p.GetSize() * 8 / maxRate);
-  Time rxTime = m_delay + txTime;
-  P2PNetDevice *to, *from;
-  if (device == m_nd1)
-    {
-      from = m_nd1;
-      to = m_nd2;
-    }
-  else
-    {
-      from = m_nd2;
-      to = m_nd1;
-    }
-  // Schedule the receive event at receiver
-  Simulator::Schedule(rxTime, &P2PNetDevice::Receive, to, p);
-  // Schedule the link free event
-  Simulator::Schedule(txTime, &P2PNetDevice::TxComplete, from);
-
-}
-
-}//namespace ns3
--- a/src/devices/p2p-gfr/p2p-channel.h	Sun May 13 10:57:43 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Definition of a simple point-to-point channel
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef P2P_CHANNEL_H
-#define P2P_CHANNEL_H
-
-#include "ns3/nstime.h"
-#include "ns3/mac-address.h"
-
-namespace ns3 {
-
-class P2PNetDevice;
-class NetDevice;
-class Node;
-class Packet;
-
-class P2PChannel  {
-public:
-  P2PChannel(const Time& delay, double maxRate /* bits/s */);
-  ~P2PChannel();
-
-  P2PNetDevice* CreateNetDevice(Node *node, MacAddress address);
-  void       RemoveNetDevice (NetDevice *device);
-  void       Send (P2PNetDevice *device, Packet&p, double rate /* bits/s */);
-private:
-  // The two endpoints of this channel
-  P2PNetDevice* m_nd1;
-  P2PNetDevice* m_nd2;
-  Time          m_delay;
-  double        m_maxRate;
-};
-
-}//namespace ns3
-
-#endif
--- a/src/devices/p2p-gfr/p2p-net-device.cc	Sun May 13 10:57:43 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Implementation of a point-to-point network device
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ns3/empty-trace-resolver.h"
-#include "p2p-net-device.h"
-#include "p2p-channel.h"
-
-namespace ns3 {
-
-P2PNetDevice::P2PNetDevice (Node *node, MacAddress const &addr)
-  : NetDevice (node, addr),
-    m_rate (1000000)
-{
-  SetMtu (2300);
-  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
-}
-
-P2PNetDevice::~P2PNetDevice()
-{ // Inform channel that we are destroyed
-  m_channel->RemoveNetDevice(this);
-}
-
-void 
-P2PNetDevice::SetRate (double rate)
-{
-  m_rate = rate;
-}
-
-void 
-P2PNetDevice::Connect (P2PChannel *channel)
-{
-  m_channel = channel;
-  NotifyLinkUp ();
-}
-
-bool 
-P2PNetDevice::SendTo (Packet& p, const MacAddress&)
-{
-  m_channel->Send (this, p, m_rate);
-  return true;
-}
-
-TraceResolver *
-P2PNetDevice::DoCreateTraceResolver (TraceContext const &context)
-{
-  return new EmptyTraceResolver (context);
-}
-
-void
-P2PNetDevice::Receive(Packet p)
-{
-  ForwardUp (p);
-}
-
-void 
-P2PNetDevice::TxComplete (void)
-{}
-
-}//namespace ns3  
--- a/src/devices/p2p-gfr/p2p-net-device.h	Sun May 13 10:57:43 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// All rights reserved.
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-// Definition for a Point-to-Point network device
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef P2P_NET_DEVICE_H
-#define P2P_NET_DEVICE_H
-
-#include "ns3/net-device.h"
-
-namespace ns3 {
-
-class P2PChannel;
-
-class P2PNetDevice : public NetDevice {
-public:
-  P2PNetDevice(Node *node, MacAddress const &addr);
-  virtual ~P2PNetDevice();
-
-  void SetRate (double rate);
-  void Connect (P2PChannel *channel);
-  void Receive(Packet p);
-  void TxComplete (void);
- private:
-  virtual bool SendTo (Packet& p, const MacAddress& dest);
-  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
-
-  double m_rate;
-  P2PChannel *m_channel;
-};
-
-}//namespace ns3
-
-#endif /* P2P_NET_DEVICE_H */
-
--- a/src/devices/p2p/p2p-topology.cc	Sun May 13 10:57:43 2007 +0200
+++ b/src/devices/p2p/p2p-topology.cc	Sun May 13 11:24:28 2007 +0200
@@ -24,6 +24,8 @@
 
 #include <algorithm>
 #include "ns3/assert.h"
+#include "ns3/debug.h"
+#include "ns3/fatal-error.h"
 #include "ns3/nstime.h"
 #include "ns3/internet-node.h"
 #include "ns3/ipv4-address.h"
@@ -60,7 +62,7 @@
   return channel;
 }
 
-bool
+void
 PointToPointTopology::AddIpv4Addresses(
   Ptr<const PointToPointChannel> chan,
   Ptr<Node> n1, const Ipv4Address& addr1,
@@ -99,111 +101,72 @@
   ip2->SetNetworkMask (index2, netmask);
   ip2->SetUp (index2);
   
-  ip1->AddHostRouteTo (addr2, index1);
-  ip2->AddHostRouteTo (addr1, index2);
-    
-  return true;
-}
-
-#ifdef NOTYET
-
-// Get the net device connecting node n1 to n2.  For topologies where
-// there are possibly multiple devices connecting n1 and n2 (for example
-// wireless with two devices on different channels) this will return
-// the first one found.
-Ptr<PointToPointNetDevice> PointToPointTopology::GetNetDevice(Ptr<Node> n1, Ptr<Node> n2)
-{
-  for (NetDeviceList::NetDevices_t::const_iterator i = dlist.Begin();
-       i != dlist.End(); ++i)
-    { // Check each device
-      Ptr<NetDevice> nd = *i; // next device
-      Ptr<Channel> c = nd->GetChannel();
-      if (!c) continue; // No channel
-      if (c->NodeIsPeer(n2)) return nd; // found it
-    }
-  return 0; // None found
-}
-  
-// Get the channel connecting node n1 to node n2
-Ptr<PointToPointChannel> PointToPointTopology::GetChannel(
-  Ptr<Node> n1, 
-  Ptr<Node> n2
-)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so no channel
-  return nd->GetChannel();
-}
-
-Ptr<Queue> PointToPointTopology::GetQueue(Ptr<Node> n1, Ptr<Node> n2)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so in queue
-  return nd->GetQueue();
-}
-
-void PointToPointTopology::SetQueue(Ptr<Node> n1, Ptr<Node> n2, Ptr<Queue> q)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, can't set queue
-  // Add the specified queue to the netdevice
-  return nd->SetQueue(q);
 }
 
-#endif
+void
+PointToPointTopology::AddIpv4Routes (
+  Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> chan)
+{ 
+  // The PointToPoint channel is used to find the relevant NetDevices
+  NS_ASSERT (chan->GetNDevices () == 2);
+  Ptr<NetDevice> nd1 = chan->GetDevice (0);
+  Ptr<NetDevice> nd2 = chan->GetDevice (1);
+
+  // Assert that n1 is the Node owning one of the two NetDevices
+  // and make sure that nd1 corresponds to it
+  if (nd1->GetNode ()->GetId () == n1->GetId ())
+    {
+      ; // Do nothing
+    }
+  else if (nd2->GetNode ()->GetId () == n1->GetId ())
+    {
+      std::swap(nd1, nd2);
+    }
+  else
+    {
+      NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
+    }
+
+   // Assert that n2 is the Node owning one of the two NetDevices
+   // and make sure that nd2 corresponds to it
+  if (nd2->GetNode ()->GetId () != n2->GetId ())
+    {
+      NS_FATAL_ERROR("P2PTopo: Node does not contain an interface on Channel");
+    }
 
-#ifdef GFR
-P2PChannel Topology::AddDuplexLink(Ptr<Node> n1, const IPAddr& ip1, 
-                                    Ptr<Node> n2, const IPAddr& ip2,
-                                    const Rate& rate, const Time& delay)
-{
-  // Get the net devices
-  P2PNetDevice* nd1 = ndl1->Add(P2PNetDevice(n1, rate, nil));
-  P2PNetDevice* nd2 = ndl2->Add(P2PNetDevice(n1, rate, nd1->GetChannel()));
-  // Not implemented yet.  Add appropriate layer 2 protocol for
-  // the net devices.
-  // Get the L3 proto for node 1 and configure it with this device
-  Ptr<L3Demux>    l3demux1 = n1->GetL3Demux();
-  Ptr<L3Protocol> l3proto1 = nil;
-  // If the node 1 l3 demux exists, find the coresponding l3 protocol
-  if (l3demux1) l3proto1 = l3demux1->Lookup(ip1.L3Proto());
-  // If the l3 protocol exists, configure this net device.  Use a mask
-  // of all ones, since there is only one device on the remote end
-  // of this link
-  if (l3proto1) l3proto1->AddNetDevice(nd1, ip1, ip1.GetMask(ip1.Size()*8));
-  // Same for node 2
-  Ptr<L3Demux>    l3demux2 = n2->GetL3Demux();
-  Ptr<L3Protocol> l3proto2 = nil;
-  // If the node 2 l3 demux exists, find the coresponding l3 protocol
-  if (l3demux2) l3proto2 = l3demux2->Lookup(ip2.L3Proto());
-  if (l3proto2) l3proto2->AddNetDevice(nd2, ip2, ip2.GetMask(ip2.Size()*8));
-  return dynamic_cast<P2PChannel*>(nd1->GetChannel());  // Always succeeds
+  // Assert that both are Ipv4 nodes
+  Ptr<IIpv4> ip1 = nd1->GetNode ()->QueryInterface<IIpv4> (IIpv4::iid);
+  Ptr<IIpv4> ip2 = nd2->GetNode ()->QueryInterface<IIpv4> (IIpv4::iid);
+  NS_ASSERT(ip1 != 0 && ip2 != 0);
+
+  // Get interface indexes for both nodes corresponding to the right channel
+  uint32_t index1 = 0;
+  bool found = false;
+  for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
+    {
+      if (ip1 ->GetNetDevice (i) == nd1)
+        {
+          index1 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  uint32_t index2 = 0;
+  found = false;
+  for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
+    {
+      if (ip2 ->GetNetDevice (i) == nd2)
+        {
+          index2 = i;
+          found = true;
+        }
+    }
+  NS_ASSERT(found);
+
+  ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
+  ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); 
 }
 
-// Get the channel connecting node n1 to node n2
-Ptr<Channel> Topology::GetChannel(Ptr<Node> n1, Ptr<Node> n2)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so no channel
-  return nd->GetChannel();
-}
-
-Ptr<Queue> Topology::GetQueue(Ptr<Node> n1, Ptr<Node> n2)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so in queue
-  return nd->GetQueue();
-}
-
-void Topology::SetQueue(Ptr<Node> n1, Ptr<Node> n2, Ptr<Queue> q)
-{
-  Ptr<NetDevice> nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, can't set queue
-  // Add the specified queue to the netdevice
-  return nd->SetQueue(q);
-}
-
-#endif
-
 } // namespace ns3
  
--- a/src/devices/p2p/p2p-topology.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/devices/p2p/p2p-topology.h	Sun May 13 11:24:28 2007 +0200
@@ -34,47 +34,51 @@
 class IPAddr;
 class DataRate;
 class Queue;
-//class Time;
 
 /**
- * \brief A helper class to create Topologies based on the ns3::PointToPointNetDevice and 
- *        ns3::PointToPointChannel objects.
- *
- * XXX ??
- * I think that some of the methods below are not implemented.
- * If so, remove them.
+ * \brief A helper class to create Topologies based on the 
+ * ns3::PointToPointNetDevice and  ns3::PointToPointChannel objects.
  */
 class PointToPointTopology {
 public:
   /** 
+   * \param n1 Node
+   * \param n2 Node
+   * \param rate Maximum transmission link rate 
+   * \param delay one-way propagation delay 
+   * \return Pointer to the underlying PointToPointChannel
+   * 
    * Add a full-duplex point-to-point link between two nodes
-   * with the specified IP addresses,  with specified maximum transmission rate
-   * and propagation delay.
+   * and attach PointToPointNetDevices to the resulting
+   * PointToPointChannel.  
    */
   static Ptr<PointToPointChannel> AddPointToPointLink(
-    Ptr<Node>, Ptr<Node>, const DataRate&, const Time&);
+    Ptr<Node> n1, Ptr<Node> n2, const DataRate& dataRate, const Time& delay);
 
-  static bool AddIpv4Addresses(
-    Ptr<const PointToPointChannel>,
-    Ptr<Node>, const Ipv4Address&,
-    Ptr<Node>, const Ipv4Address&);
+  /** 
+   * \param chan PointToPointChannel to use
+   * \param n1 Node
+   * \param addr1 Ipv4 Address for n1
+   * \param n2 Node
+   * \param addr2 Ipv4 Address for n2
+   * 
+   * Add Ipv4Addresses to the Ipv4 interfaces associated with the 
+   * two PointToPointNetDevices on the provided PointToPointChannel
+   */
+  static void AddIpv4Addresses(
+    Ptr<const PointToPointChannel> chan,
+    Ptr<Node> n1, const Ipv4Address& addr1,
+    Ptr<Node> n2, const Ipv4Address& addr2);
 
   /**
-   * Get the connecting node n1 to node n2
-   */
-  static Ptr<PointToPointChannel> GetChannel(Ptr<Node>, Ptr<Node>);
-  /**
-   * Get the NetDevice connecting node n1 to n2
+   * \param channel PointToPointChannel to use
+   * \param n1 Node
+   * \param n2 Node
+   * 
+   * For the given PointToPointChannel, for each Node, add an 
+   * IPv4 host route to the IPv4 address of the peer node.  
    */
-  static Ptr<PointToPointNetDevice> GetNetDevice(Ptr<Node>, Ptr<Node>);
-  /**
-   * Get the queue associated with a link between two nodes
-   */
-  static Queue* GetQueue(Ptr<Node>, Ptr<Node>);
-  /**
-   * Set the queue associated with a link between two nodes
-   */
-  static Queue* SetQueue(Ptr<Node>, Ptr<Node>, const Queue&);
+  static void AddIpv4Routes (Ptr<Node> n1, Ptr<Node> n2, Ptr<const PointToPointChannel> channel);
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,18 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    p2p = bld.create_obj('cpp', 'shlib')
+    p2p.name = 'ns3-p2p'
+    p2p.target = p2p.name
+    p2p.deps = ['ns3-node']
+    p2p.source = [
+        'p2p-net-device.cc',
+        'p2p-channel.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'p2p-net-device.h',
+        'p2p-channel.h',
+        ]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,6 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    bld.add_subdirs('p2p')
+    #bld.add_subdirs('p2p-gfr')
+
--- a/src/internet-node/i-ipv4-impl.cc	Sun May 13 10:57:43 2007 +0200
+++ b/src/internet-node/i-ipv4-impl.cc	Sun May 13 11:24:28 2007 +0200
@@ -20,6 +20,7 @@
  */
 #include "i-ipv4-impl.h"
 #include "ipv4.h"
+#include "ipv4-interface.h"
 #include "ns3/assert.h"
 #include "ns3/net-device.h"
 
@@ -97,6 +98,11 @@
 {
   return m_ipv4->GetNInterfaces ();
 }
+Ptr<NetDevice>
+IIpv4Impl::GetNetDevice (uint32_t i)
+{
+  return m_ipv4->GetInterface (i)-> GetDevice ();
+}
 
 void 
 IIpv4Impl::SetAddress (uint32_t i, Ipv4Address address)
--- a/src/internet-node/i-ipv4-impl.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/internet-node/i-ipv4-impl.h	Sun May 13 11:24:28 2007 +0200
@@ -54,6 +54,7 @@
   virtual void RemoveRoute (uint32_t i);
   virtual uint32_t AddInterface (Ptr<NetDevice> device);
   virtual uint32_t GetNInterfaces (void);  
+  virtual Ptr<NetDevice> GetNetDevice(uint32_t i);
 
   virtual void SetAddress (uint32_t i, Ipv4Address address);
   virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-node/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,43 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    obj = bld.create_obj('cpp', 'shlib')
+    obj.name = 'ns3-internet-node'
+    obj.target = obj.name
+    obj.deps = ['ns3-node', 'ns3-applications']
+    obj.source = [
+        'internet-node.cc',
+        'l3-demux.cc',
+        'l3-protocol.cc',
+        'ipv4-l4-demux.cc',
+        'ipv4-l4-protocol.cc',
+        'ipv4-header.cc',
+        'udp-header.cc',
+        'ipv4-checksum.cc',
+        'ipv4-interface.cc',
+        'ipv4.cc',
+        'ipv4-end-point.cc',
+        'udp.cc',
+        'arp-header.cc',
+        'arp-cache.cc',
+        'arp-ipv4-interface.cc',
+        'arp.cc',
+        'ipv4-loopback-interface.cc',
+        'header-utils.cc',
+        'udp-socket.cc',
+        'ipv4-end-point-demux.cc',
+        'i-udp-impl.cc',
+        'i-arp-private.cc',
+        'i-ipv4-impl.cc',
+        'i-ipv4-private.cc',
+        'ascii-trace.cc',
+        'pcap-trace.cc',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'internet-node.h',
+        'ascii-trace.h',
+        'pcap-trace.h',
+        ]
--- a/src/node/application.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/node/application.h	Sun May 13 11:24:28 2007 +0200
@@ -21,32 +21,6 @@
 #ifndef __APPLICATION_H__
 #define __APPLICATION_H__
 
-//
-// \brief The base class for all ns3 applicationes
-//
-// Class Application is the base class for all ns3 applications.
-// Applications are associated with individual nodes, and are created
-// using the AddApplication method in the ApplicationManager capability.
-// 
-// Conceptually, an application has zero or more Socket
-// objects associated with it, that are created using the Socket
-// creation API of the Kernel capability.  The Socket object
-// API is modeled after the
-// well-known BSD sockets interface, although it is somewhat 
-// simplified for use with ns3.  Further, any socket call that
-// would normally "block" in normal sockets will return immediately
-// in ns3.  A set of "upcalls" are defined that will be called when
-// the previous blocking call would normally exit.  THis is documented
-// in more detail Socket class in socket.h.
-// 
-// There is a second application class in ns3, called "ThreadedApplication"
-// that implements a true sockets interface, which should be used
-// when porting existing sockets code to ns3.  The true
-// sockets approach is significantly
-// less memory--efficient using private stacks for each defined application,
-// so that approach should be used with care.  The design and implementation
-// of the ThreadedApplication are still being discussed.
-
 #include "ns3/event-id.h"
 #include "ns3/nstime.h"
 #include "ns3/object.h"
@@ -59,7 +33,21 @@
 class RandomVariable;
 
 /**
- * \brief a model for userspace applications.
+ * \brief The base class for all ns3 applicationes
+ * 
+ * Class Application is the base class for all ns3 applications.
+ * Applications are associated with individual nodes.
+ * 
+ * Conceptually, an application has zero or more Socket
+ * objects associated with it, that are created using the Socket
+ * creation API of the Kernel capability.  The Socket object
+ * API is modeled after the
+ * well-known BSD sockets interface, although it is somewhat 
+ * simplified for use with ns3.  Further, any socket call that
+ * would normally "block" in normal sockets will return immediately
+ * in ns3.  A set of "upcalls" are defined that will be called when
+ * the previous blocking call would normally exit.  THis is documented
+ * in more detail Socket class in socket.h.
  */
 class Application : public Object
 {
--- a/src/node/i-ipv4.h	Sun May 13 10:57:43 2007 +0200
+++ b/src/node/i-ipv4.h	Sun May 13 11:24:28 2007 +0200
@@ -122,6 +122,12 @@
    */
   virtual uint32_t GetNInterfaces (void) = 0;  
 
+  /**
+   * \param index of interface
+   * \returns address of the NetDevice associated with the ipv4 interface
+   */
+  virtual Ptr<NetDevice> GetNetDevice (uint32_t i) = 0;
+
   virtual void SetAddress (uint32_t i, Ipv4Address address) = 0;
   virtual void SetNetworkMask (uint32_t i, Ipv4Mask mask) = 0;
   virtual Ipv4Mask GetNetworkMask (uint32_t t) const = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,40 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+
+def build(bld):
+    node = bld.create_obj('cpp', 'shlib')
+    node.name = 'ns3-node'
+    node.target = node.name
+    node.deps = ['ns3-core', 'ns3-common', 'ns3-simulator']
+    node.source = [
+        'node.cc',
+        'ipv4-address.cc',
+        'net-device.cc',
+        'mac-address.cc',
+        'llc-snap-header.cc',
+        'ipv4-route.cc',
+        'queue.cc',
+        'drop-tail.cc',
+        'channel.cc',
+        'node-list.cc',
+        'socket.cc',
+        'i-udp.cc',
+        'i-ipv4.cc',
+        ]
+
+    headers = bld.create_obj('ns3header')
+    headers.source = [
+        'node.h',
+        'ipv4-address.h',
+        'net-device.h',
+        'mac-address.h',
+        'ipv4-route.h',
+        'queue.h',
+        'drop-tail.h',
+        'llc-snap-header.h',
+        'channel.h',
+        'node-list.h',
+        'socket.h',
+        'i-udp.h',
+        'i-ipv4.h',
+        ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/simulator/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,95 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import sys
+
+import Params
+
+
+def set_options(opt):
+    opt.add_option('--high-precision-as-double',
+                   help=('Whether to use a double floating point'
+                         ' type for high precision time values'),
+                   action="store_true", default=False,
+                   dest='high_precision_as_double')
+
+
+def configure(conf):
+    if Params.g_options.high_precision_as_double:
+        conf.add_define('USE_HIGH_PRECISION_DOUBLE', 1)
+        conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1
+        highprec = 'long double'
+    else:
+        conf.env['USE_HIGH_PRECISION_DOUBLE'] = 0
+        highprec = '128-bit integer'
+    conf.check_message_custom('high precision time', 'implementation', highprec)
+
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'stdint.h'
+    e.define = 'HAVE_STDINT_H'
+    e.run()
+
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'inttypes.h'
+    e.define = 'HAVE_INTTYPES_H'
+    e.run()
+
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'sys/inttypes.h'
+    e.define = 'HAVE_SYS_INT_TYPES_H'
+    e.run()
+
+    conf.write_config_header('ns3/simulator-config.h')
+
+
+
+def build(bld):
+    sim = bld.create_obj('cpp', 'shlib')
+    sim.name = 'ns3-simulator'
+    sim.target = sim.name
+    sim.deps = 'ns3-simulator-headers ns3-core-headers'
+
+    sim.source = [
+        'high-precision.cc',
+        'time.cc',
+        'event-id.cc',
+        'scheduler.cc',
+        'scheduler-factory.cc',
+        'scheduler-list.cc',
+        'scheduler-heap.cc',
+        'scheduler-map.cc',
+        'event-impl.cc',
+        'simulator.cc',
+        ]
+    headers = bld.create_obj('ns3header')
+    headers.name = 'ns3-simulator-headers'
+    headers.source = [
+        'high-precision.h',
+        'nstime.h',
+        'event-id.h',
+        'event-impl.h',
+        'simulator.h',
+        'scheduler.h',
+        'scheduler-factory.h',
+        'simulation-singleton.h',
+        ]
+
+    env = bld.env_of_name('default')
+    if env['USE_HIGH_PRECISION_DOUBLE']:
+        sim.source.extend([
+            'high-precision-double.cc',
+            ])
+        headers.source.extend([
+            'high-precision-double.h',
+            ])
+    else:
+        sim.source.extend([
+            'high-precision-128.cc',
+            'cairo-wideint.c',
+            ])
+        headers.source.extend([
+            'high-precision-128.h',
+            'cairo-wideint-private.h',
+            ])
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,13 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def set_options(opt):
+    opt.sub_options('simulator')
+
+def configure(conf):
+    conf.sub_config('core')
+    conf.sub_config('simulator')
+
+def build(bld):
+    bld.add_subdirs('core common simulator')
+    bld.add_subdirs('node internet-node devices applications')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/utils/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,25 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import sys
+import Params
+
+def build(bld):
+
+    def create_ns_prog(name, source):
+        obj = bld.create_obj('cpp', 'program')
+        obj.target = name
+        obj.deps = "ns3-core ns3-common ns3-simulator"
+        obj.uselib_local = "ns3-core ns3-common ns3-simulator"
+        obj.source = source
+        for module in ['core', 'common', 'simulator']:
+            obj.env.append_value('RPATH', r'-Wl,--rpath=\$ORIGIN/../src/%s' % (module,))
+        return obj
+
+    unit_tests = create_ns_prog('run-tests', 'run-tests.cc')
+    unit_tests.install_var  = 0 #do not install
+    unit_tests.unit_test    = 1
+    
+    #if sys.platform != 'win32':
+    obj = create_ns_prog('bench-simulator', 'bench-simulator.cc')
+    obj = create_ns_prog('replay-simulation', 'replay-simulation.cc')
+    ## bench-packets requires missing header files
+    #obj = create_ns_prog('bench-packets', 'bench-packets.cc')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wscript	Sun May 13 11:24:28 2007 +0200
@@ -0,0 +1,183 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+import os
+
+import Params
+import Object
+import Action
+import Common
+import shutil
+import subprocess
+
+Params.g_autoconfig = 1
+
+# the following two variables are used by the target "waf dist"
+VERSION = '3.0.1'
+APPNAME = 'ns-3-waf'
+
+# these variables are mandatory ('/' are converted automatically)
+srcdir = '.'
+blddir = 'build'
+
+class Ns3Header(Object.genobj):
+    """A public NS-3 header file"""
+    def __init__(self, env=None):
+        Object.genobj.__init__(self, 'other')
+        self.inst_var = 'INCLUDEDIR'
+        self.inst_dir = 'ns3'
+        self.env = env
+        if not self.env:
+            self.env = Params.g_build.m_allenvs['default']
+
+    def apply(self):
+        ns3_dir_node = Params.g_build.m_srcnode.find_dir("ns3")
+        inputs = []
+        outputs = []
+        for filename in self.to_list(self.source):
+            src_node = self.path.find_source(filename)
+            if src_node is None:
+                Params.fatal("source ns3 header file %s not found" % (filename,))
+            dst_node = ns3_dir_node.find_build(os.path.basename(filename))
+            assert dst_node is not None
+            inputs.append(src_node)
+            outputs.append(dst_node)
+        task = self.create_task('ns3_headers', self.env, 1)
+        task.set_inputs(inputs)
+        task.set_outputs(outputs)
+
+    def install(self):
+        for i in self.m_tasks:
+            current = Params.g_build.m_curdirnode
+            lst = map(lambda a: a.relpath_gen(current), i.m_outputs)
+            Common.install_files(self.inst_var, self.inst_dir, lst)
+
+def _ns3_headers_inst(task):
+    assert len(task.m_inputs) == len(task.m_outputs)
+    inputs = [node.srcpath(task.m_env) for node in task.m_inputs]
+    outputs = [node.bldpath(task.m_env) for node in task.m_outputs]
+    for src, dst in zip(inputs, outputs):
+        try:
+            os.chmod(dst, 0600)
+        except OSError:
+            pass
+        shutil.copy2(src, dst)
+        ## make the headers in builddir read-only, to prevent
+        ## accidental modification
+        os.chmod(dst, 0400)
+    return 0
+
+def init():
+    Object.register('ns3header', Ns3Header)
+    Action.Action('ns3_headers', func=_ns3_headers_inst, color='BLUE')
+
+def set_options(opt):
+    # options provided by the modules
+    if not opt.tool_options('msvc'):
+        opt.tool_options('g++')
+
+    opt.add_option('--enable-gcov',
+                   help=('Enable code coverage analysis'),
+                   action="store_true", default=False,
+                   dest='enable_gcov')
+
+    opt.add_option('--lcov-report',
+                   help=('Generate a code coverage report '
+                         '(use this option at build time, not in configure)'),
+                   action="store_true", default=False,
+                   dest='lcov_report')
+
+    opt.add_option('--doxygen',
+                   help=('Run doxygen to generate html documentation from source comments'),
+                   action="store_true", default=False,
+                   dest='doxygen')
+
+    # options provided in a script in a subdirectory named "src"
+    opt.sub_options('src')
+
+
+def configure(conf):
+    if not conf.check_tool('msvc'):
+        if not conf.check_tool('g++'):
+            Params.fatal("No suitable compiler found")
+
+
+    # create the second environment, set the variant and set its name
+    variant_env = conf.env.copy()
+    variant_name = Params.g_options.debug_level.lower()
+
+    if Params.g_options.enable_gcov:
+        variant_name += '-gcov'
+        variant_env.append_value('CCFLAGS', '-fprofile-arcs')
+        variant_env.append_value('CCFLAGS', '-ftest-coverage')
+        variant_env.append_value('CXXFLAGS', '-fprofile-arcs')
+        variant_env.append_value('CXXFLAGS', '-ftest-coverage')
+        variant_env.append_value('LINKFLAGS', '-fprofile-arcs')
+    
+    conf.env['NS3_ACTIVE_VARIANT'] = variant_name
+    variant_env['NS3_ACTIVE_VARIANT'] = variant_name
+    variant_env.set_variant(variant_name)
+    conf.set_env_name(variant_name, variant_env)
+    conf.setenv(variant_name)
+
+    variant_env.append_value('CXXDEFINES', 'RUN_SELF_TESTS')
+    if 'debug' in Params.g_options.debug_level.lower():
+        variant_env.append_value('CXXDEFINES', 'NS3_DEBUG_ENABLE')
+        variant_env.append_value('CXXDEFINES', 'NS3_ASSERT_ENABLE')
+
+    conf.sub_config('src')
+
+
+def build(bld):
+    variant_name = bld.env_of_name('default')['NS3_ACTIVE_VARIANT']
+    variant_env = bld.env_of_name(variant_name)
+    bld.m_allenvs['default'] = variant_env # switch to the active variant
+    # process subfolders from here
+    bld.add_subdirs('src')
+    bld.add_subdirs('samples utils')
+
+
+def shutdown():
+    import UnitTest
+    ut = UnitTest.unit_test()
+    ut.change_to_testfile_dir = True
+    ut.want_to_see_test_output = True
+    ut.want_to_see_test_error = True
+    ut.run()
+    #ut.print_results()
+
+    if Params.g_options.lcov_report:
+        env = Params.g_build.env_of_name('default')
+        variant_name = env['NS3_ACTIVE_VARIANT']
+
+        if 'gcov' not in variant_name:
+            Params.fatal("project not configured for code coverage;"
+                         " reconfigure with --enable-gcov")
+        
+        os.chdir(blddir)
+        try:
+            lcov_report_dir = os.path.join(variant_name, 'lcov-report')
+            create_dir_command = "rm -rf " + lcov_report_dir
+            create_dir_command += " && mkdir " + lcov_report_dir + ";"
+
+            if subprocess.Popen(create_dir_command, shell=True).wait():
+                raise SystemExit(1)
+
+            info_file = os.path.join(lcov_report_dir, variant_name + '.info')
+            lcov_command = "../utils/lcov/lcov -c -d . -o " + info_file
+            lcov_command += " --source-dirs=" + os.getcwd()
+            lcov_command += ":" + os.path.join(
+                os.getcwd(), variant_name, 'include')
+            if subprocess.Popen(lcov_command, shell=True).wait():
+                raise SystemExit(1)
+
+            genhtml_command = "../utils/lcov/genhtml -o " + lcov_report_dir
+            genhtml_command += " " + info_file
+            if subprocess.Popen(genhtml_command, shell=True).wait():
+                raise SystemExit(1)
+        finally:
+            os.chdir("..")
+
+    if Params.g_options.doxygen:
+        doxygen_config = os.path.join('doc', 'doxygen.conf')
+        if subprocess.Popen(['doxygen', doxygen_config]).wait():
+            raise SystemExit(1)
+