Remove regression tests from waf
authorMitch Watrous <watrous@u.washington.edu>
Fri, 15 Oct 2010 16:31:32 -0700
changeset 6624 a071889af159
parent 6623 616d42c69f05
child 6625 edc862ef7d63
Remove regression tests from waf
CHANGES.html
doc/manual/tcp.texi
doc/release_steps.txt
doc/tutorial/conceptual-overview.texi
doc/tutorial/getting-started.texi
src/test/csma-system-test-suite.cc
src/test/global-routing-test-suite.cc
src/test/static-routing-test-suite.cc
src/test/wscript
wscript
wutils.py
--- a/CHANGES.html	Fri Oct 15 12:53:05 2010 -0700
+++ b/CHANGES.html	Fri Oct 15 16:31:32 2010 -0700
@@ -47,6 +47,11 @@
 <h1>Changes from ns-3.9 to ns-3.10</h1>
 
 <h2>Changes to build system:</h2>
+<ul>
+<li><b>Regression tests are no longer run using waf</b>
+<p>All regression testing is now being done in test.py.  As a result, reference traces are no longer needed in ns-3 to perform regression testing.
+</p>
+</ul>
 
 <h2>New API:</h2>
 
--- a/doc/manual/tcp.texi	Fri Oct 15 12:53:05 2010 -0700
+++ b/doc/manual/tcp.texi	Fri Oct 15 16:31:32 2010 -0700
@@ -148,10 +148,10 @@
 additional arguments are needed for waf.  Building nsc may take some time
 compared to ns-3; it is interleaved in the ns-3 building process.
 
-Try running the regression tests: @code{./waf --regression}.  If NSC has
-been successfully built, the following test should show up in the results:
+Try running the following ns-3 test suite: @code{./test.py -s ns3-tcp-interoperability}.  If NSC has
+been successfully built, the following should show up in the results:
 @verbatim
-PASS test-tcp-nsc-lfn
+PASS: TestSuite ns3-tcp-interoperability
 @end verbatim
 
 This confirms that NSC is ready to use.
--- a/doc/release_steps.txt	Fri Oct 15 12:53:05 2010 -0700
+++ b/doc/release_steps.txt	Fri Oct 15 16:31:32 2010 -0700
@@ -7,7 +7,6 @@
    - confirm that the release builds cleanly.
    - cd ns-3-dev
    - ensure that tests pass (./test.py)
-   - ensure no regressions (./waf --regression)
 2. prepare the source files
    - revise and check in AUTHORS, if needed
    - revise and check in RELEASE_NOTES.  Make sure to add the Availability 
@@ -21,29 +20,22 @@
    - this will create an ns-allinone-dev.tar.bz2 tarball
 4. test dev tarball on release platforms 
    - ./test.py 
-   - ./waf --regression
    - other scripts you can think of
-5. once you are happy with the tarball, tag ns-3-dev and ns-3-dev-ref-traces
+5. once you are happy with the tarball and tag ns-3-dev
    - cd into ns-3-dev
    - hg tag "ns-3.x"
    - hg push 
-   - cd into ns-3-dev-ref-traces
-   - hg tag "ns-3.x"
-   - hg push 
 6. clone the tagged ns-3-dev and place it on the repository
    - ssh code.nsnam.org; sudo bash; su code;
    - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.x
    - cd /home/code/repos/ns-3.x/.hg and edit the hgrc appropriately:
      "description = ns-3.x release
       name = ns-3.x"
-   - clone the ns-3-dev-ref-traces and place it on the repository as above
-     but use the name ns-3.x-ref-traces and edit the hgrc appropriately
 7. check out a clean version of the new release (ns-3.x) somewhere
    - hg clone http://code.nsnam.org/ns-3.x
 8. Update the VERSION for this new release
    - change the string 3-dev in the VERSION file to the real version 
-     (e.g. 3.7 or 3.7-RC1)  This must agree with the version name you chose in the clone
-     for the regression tests to work.
+     (e.g. 3.7 or 3.7-RC1)  This must agree with the version name you chose in the clone.
    - hg commit -m "update VERSION to ns-3.x"
    - hg push ssh://code@code.nsnam.org//home/code/repos/ns-3.x
 
@@ -51,25 +43,21 @@
    You need to use ns-3-allinone since you will use that to make the distro
    - hg clone http://code.nsnam.org/ns-3-allinone ns-3-allinone-3.x-test
    - cd !$
-   - ./download.py -n ns-3.x -r ns-3.x-ref-traces
+   - ./download.py -n ns-3.x
    - ./build.py
    - cd ns-3.x
    - ./test.py
    - ./test.py -g
-   - ./waf --regression
-   - ./waf --valgrind --regression (for valgrind version)
    - ./waf -d optimized configure
    - ./waf
    - ./test.py
    - ./test.py -g
-   - ./waf --regression
-   - ./waf --valgrind --regression (for valgrind version)
-   - There should be no regression errors at this time
+   - There should be no test errors at this time
 10. Create final tarballs
     You need to work with a clean ns-3-allinone-3.x directory
    - hg clone http://code.nsnam.org/ns-3-allinone ns-3-allinone-3.x
    - cd !$
-   - ./download.py -n ns-3.x -r ns-3.x-ref-traces
+   - ./download.py -n ns-3.x
    - ./dist.py
    - notice we did not build here
    - this will create an ns-allinone-3.x.tar.bz2 tarball
@@ -110,9 +98,9 @@
         necessary files
 16. Final checks
    - check manual, testing, and tutorial documentation links
-   - download tarball from web, build and run regression tests for as many
+   - download tarball from web, build and run tests for as many
      targets as you can
-   - download release from mercurial, build and run regression tests for as
+   - download release from mercurial, build and run tests for as
      many targets as you can
    - test and verify until you're confident the release is solid.
 17. announce to ns-developers, with summary of release notes
--- a/doc/tutorial/conceptual-overview.texi	Fri Oct 15 12:53:05 2010 -0700
+++ b/doc/tutorial/conceptual-overview.texi	Fri Oct 15 16:31:32 2010 -0700
@@ -174,10 +174,10 @@
 directory structure something like the following:
 
 @verbatim
-  AUTHORS       doc/       README          RELEASE_NOTES  utils/    wscript
-  bindings/     examples/  regression/     samples/       VERSION   wutils.py
-  build/        LICENSE    regression.py   scratch/       waf*      wutils.pyc
-  CHANGES.html  ns3/       regression.pyc  src/           waf.bat*
+  AUTHORS       doc/       README         src/     waf.bat*
+  bindings/     examples/  RELEASE_NOTES  utils/   wscript
+  build/        LICENSE    samples/       VERSION  wutils.py
+  CHANGES.html  ns3/       scratch/       waf*     wutils.pyc
 @end verbatim
 
 @cindex first.cc
@@ -811,7 +811,6 @@
 drwxr-xr-x                               doc              files
 drwxr-xr-x                               examples         files
 drwxr-xr-x                               ns3              files
-drwxr-xr-x                               regression       files
 drwxr-xr-x                               samples          files
 drwxr-xr-x                               scratch          files
 drwxr-xr-x                               src              files
@@ -824,7 +823,6 @@
 -rw-r--r-- 2009-07-01 12:47 +0200 3742   README           file | revisions | annotate
 -rw-r--r-- 2009-07-01 12:47 +0200 16171  RELEASE_NOTES    file | revisions | annotate
 -rw-r--r-- 2009-07-01 12:47 +0200 6      VERSION          file | revisions | annotate
--rw-r--r-- 2009-07-01 12:47 +0200 10946  regression.py    file | revisions | annotate
 -rwxr-xr-x 2009-07-01 12:47 +0200 88110  waf              file | revisions | annotate
 -rwxr-xr-x 2009-07-01 12:47 +0200 28     waf.bat          file | revisions | annotate
 -rw-r--r-- 2009-07-01 12:47 +0200 35395  wscript          file | revisions | annotate
--- a/doc/tutorial/getting-started.texi	Fri Oct 15 12:53:05 2010 -0700
+++ b/doc/tutorial/getting-started.texi	Fri Oct 15 16:31:32 2010 -0700
@@ -126,20 +126,8 @@
 still hypothetical release nine of @command{ns-3} would be numbered as
 @code{ns-3.9.2}.
 
-We have had a regression testing framework in place since the first release.
-For each release, a set of output files that define ``good behavior'' are saved.
-These known good output files are called reference traces and are associated 
-with a given release by name.  For example, in @uref{http://code.nsnam.org/}
-you will find a repository named @code{ns-3.1} which is the first stable release
-of @command{ns-3}.  You will also find a separate repository named 
-@code{ns-3.1-ref-traces} that holds the reference traces for the @code{ns-3.1}
-release.  It is crucial to keep these files consistent if you want to do any
-regression testing of your repository.  This is a good idea to do at least once
-to verify everything has built correctly.
-
 The current development snapshot (unreleased) of @command{ns-3} may be found 
-at @uref{http://code.nsnam.org/ns-3-dev/} and the associated reference traces
-may be found at @uref{http://code.nsnam.org/ns-3-dev-ref-traces/}.  The 
+at @uref{http://code.nsnam.org/ns-3-dev/}.  The 
 developers attempt to keep these repository in consistent, working states but
 they are in a development area with unreleased code present, so you may want 
 to consider staying with an official release if you do not need newly-
@@ -147,8 +135,8 @@
 
 Since the release numbers are going to be changing, I will stick with 
 the more constant ns-3-dev here in the tutorial, but you can replace the 
-string ``ns-3-dev'' with your choice of release (e.g., ns-3.6 and 
-ns-3.6-ref-traces) in the text below.  You can find the latest version  of the
+string ``ns-3-dev'' with your choice of release (e.g., ns-3.6) in the 
+text below.  You can find the latest version  of the
 code either by inspection of the repository list or by going to the 
 @uref{http://www.nsnam.org/getting_started.html,,``Getting Started''} 
 web page and looking for the latest release identifier.
@@ -159,15 +147,14 @@
 
 Go ahead and type the following into your shell (remember you can substitute
 the name of your chosen release number instead of @code{ns-3-dev} -- like
-@code{"ns-3.6"} and @code{"ns-3.6-ref-traces"} if you want to work with a 
+@code{"ns-3.6"} if you want to work with a 
 stable release).
 
 @verbatim
-  ./download.py -n ns-3-dev -r ns-3-dev-ref-traces
+  ./download.py -n ns-3-dev
 @end verbatim
 
-Note that the default for the @code{-n} option is @code{ns-3-dev} and the 
-default for the @code{-r} option is @code{ns-3-dev-ref-traces} and so the
+Note that the default for the @code{-n} option is @code{ns-3-dev} and so the
 above is actually redundant.  We provide this example to illustrate how to
 specify alternate repositories.  In order to download @code{ns-3-dev} you 
 can actually use the defaults and simply type,
@@ -195,24 +182,8 @@
 @end verbatim
 
 This is output by the download script as it fetches the actual @code{ns-3}
-code from the repository.  Next, you should see something like,
+code from the repository.
 
-@verbatim
-      #
-      # Get the regression traces
-      #
-  
-  Synchronizing reference traces using Mercurial.
-   =>  hg clone http://code.nsnam.org/ns-3-dev-ref-traces ns-3-dev-ref-traces
-  requesting all changes
-  adding changesets
-  adding manifests
-  adding file changes
-  added 86 changesets with 1178 changes to 259 files
-  208 files updated, 0 files merged, 0 files removed, 0 files unresolved
-@end verbatim
-
-This is the download script fetching the reference trace files for you.
 The download script is smart enough to know that on some platforms various
 pieces of ns-3 are not supported.  On your platform you may not see some
 of these pieces come down.  However, on most platforms, the process should
@@ -254,22 +225,22 @@
 Cradle for you. Note that NSC is not supported on OSX or Cygwin and works 
 best with gcc-3.4 or gcc-4.2 or greater series.
 
-After the clone command completes, you should have several new directories
+After the download.py script completes, you should have several new directories
 under @code{~/repos/ns-3-allinone}:
 
 @verbatim
-  build.py*     constants.pyc  download.py*  ns-3-dev-ref-traces/  pybindgen/  util.py
-  constants.py  dist.py*       ns-3-dev/     nsc/                  README      util.pyc
+  build.py*     constants.pyc  download.py*  nsc/        README      util.pyc
+  constants.py  dist.py*       ns-3-dev/     pybindgen/  util.py
 @end verbatim
 
 Go ahead and change into @code{ns-3-dev} under your @code{~/repos/ns-3-allinone} 
 directory.  You should see something like the following there:
 
 @verbatim
-  AUTHORS       examples/  regression/    scratch/  waf*
-  bindings/     LICENSE    regression.py  src/      waf.bat*
-  CHANGES.html  ns3/       RELEASE_NOTES  utils/    wscript
-  doc/          README     samples/       VERSION   wutils.py
+  AUTHORS       examples/  RELEASE_NOTES  utils/   wscript
+  bindings/     LICENSE    samples/       VERSION  wutils.py
+  CHANGES.html  ns3/       scratch/       waf*
+  doc/          README     src/           waf.bat*
 @end verbatim
 
 You are now ready to build the @command{ns-3} distribution.
@@ -299,8 +270,8 @@
 number of files:
 
 @verbatim
-build.py*     ns-3.6/             nsc-0.5.1/             README
-constants.py  ns-3.6-ref-traces/  pybindgen-0.12.0.700/  util.py
+build.py*     ns-3.6/     pybindgen-0.12.0.700/  util.py
+constants.py  nsc-0.5.1/  README
 @end verbatim 
 
 You are now ready to build the @command{ns-3} distribution.
@@ -355,7 +326,6 @@
 @cindex building debug version with Waf
 @cindex compiling with Waf
 @cindex unit tests with Waf
-@cindex regression tests with Waf
 We use Waf to configure and build the @command{ns-3} project.  It's not 
 strictly required at this point, but it will be valuable to take a slight
 detour and look at how to make changes to the configuration of the project.
@@ -380,7 +350,6 @@
   Checking for program ranlib              : ok /usr/bin/ranlib
   Checking for g++                         : ok
   Checking for program pkg-config          : ok /usr/bin/pkg-config
-  Checking for regression reference traces  : ok ../ns-3-dev-ref-traces (guessed)
   Checking for -Wno-error=deprecated-declarations support : yes
   Checking for -Wl,--soname=foo support                   : yes
   Checking for header stdlib.h                            : ok
@@ -530,74 +499,6 @@
 This command is typically run by @code{users} to quickly verify that an 
 @command{ns-3} distribution has built correctly.  
 
-@cindex regression tests
-You can also run our regression test suite to ensure that your distribution and
-toolchain have produced binaries that generate output that is identical to
-known-good reference output files.  You downloaded these reference traces to 
-your machine during the @code{./download.py} process above.  (Warning:  The 
-@code{ns-3.2} and @code{ns-3.3} releases do not use the @code{ns-3-allinone} 
-environment and require you to be online when you run regression tests because 
-they dynamically synchronize the reference traces directory with an online
-repository immediately prior to the run).
-
-During regression testing Waf will run a number of tests that generate what we
-call trace files.  The content of these trace files are compared with the 
-reference traces.  If they are identical, the regression tests report a PASS 
-status.  If a regression test fails you will see a FAIL indication along with a
-pointer to the offending trace file and its associated reference trace file
-along with a suggestion on diff parameters and options in order to see what 
-has gone awry.  If the error was discovered in a pcap file, it will be useful
-to convert the pcap files to text using tcpdump prior to comparison.
-
-Some regression tests may be SKIPped if the required support
-is not present.
-
-Note that the regression tests are also run in parallel and so the messages
-may be interleaved.
-
-To run the regression tests, you provide Waf with the regression flag.
-
-@verbatim
-  ./waf --regression
-@end verbatim
-
-You should see messages indicating that many tests are being run and are
-passing.
-
-@verbatim
-  Entering directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
-  [647/669] regression-test (test-csma-bridge)
-  [648/669] regression-test (test-csma-broadcast)
-  [649/669] regression-test (test-csma-multicast)
-  [650/669] regression-test (test-csma-one-subnet)
-  PASS test-csma-multicast
-  [651/669] regression-test (test-csma-packet-socket)
-  PASS test-csma-bridge
-  ...
-  Regression testing summary:
-  PASS: 22 of 22 tests passed
-  Waf: Leaving directory `/home/craigdo/repos/ns-3-allinone/ns-3-dev/build'
-  'build' finished successfully (25.826s)
-@end verbatim
-
-If you want to take a look at an example of what might be checked during
-a regression test, you can do the following:
-
-@verbatim
-  cd build/debug/regression/traces/second.ref
-  tcpdump -nn -tt -r second-2-0.pcap
-@end verbatim
-
-The output should be clear to anyone who is familiar with tcpdump or net
-sniffers.  We'll have much more to say on pcap files later in this tutorial.
-
-Remember to cd back into the top-level @command{ns-3} directory
-after you are done:
-
-@verbatim
-  cd ../../../../..
-@end verbatim
-
 @c ========================================================================
 @c Running a Script
 @c ========================================================================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/csma-system-test-suite.cc	Fri Oct 15 16:31:32 2010 -0700
@@ -0,0 +1,1126 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+// This is not a test of CsmaNetDevice model behavior per-se, but
+// instead is a roll up of several end-to-end examples in examples/csma
+// directory, converted into system tests.  Writing a test suite
+// to test Csma itself is for further study.
+
+#include <string>
+
+#include "ns3/address.h"
+#include "ns3/application-container.h"
+#include "ns3/bridge-helper.h"
+#include "ns3/callback.h"
+#include "ns3/config.h"
+#include "ns3/csma-helper.h"
+#include "ns3/csma-star-helper.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/ipv4-static-routing-helper.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/on-off-helper.h"
+#include "ns3/packet.h"
+#include "ns3/packet-sink-helper.h"
+#include "ns3/packet-socket-helper.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/pointer.h"
+#include "ns3/random-variable.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/uinteger.h"
+#include "ns3/v4ping-helper.h"
+
+using namespace ns3;
+
+class CsmaBridgeTestCase : public TestCase
+{
+public:
+  CsmaBridgeTestCase ();
+  virtual ~CsmaBridgeTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (Ptr<const Packet> p, const Address &ad);
+  uint32_t m_count;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaBridgeTestCase::CsmaBridgeTestCase ()
+  : TestCase ("Bridge example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0)
+{
+}
+
+CsmaBridgeTestCase::~CsmaBridgeTestCase ()
+{
+}
+
+void 
+CsmaBridgeTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+  m_count++;
+}
+
+// Network topology
+//
+//        n0     n1  
+//        |      | 
+//       ----------
+//       | Switch |
+//       ----------
+//        |      | 
+//        n2     n3  
+//
+// - CBR/UDP test flow from n0 to n1; test that packets received on n1 
+//
+bool
+CsmaBridgeTestCase::DoRun (void)
+{
+  NodeContainer terminals;
+  terminals.Create (4);
+
+  NodeContainer csmaSwitch;
+  csmaSwitch.Create (1);
+
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+
+  NetDeviceContainer terminalDevices;
+  NetDeviceContainer switchDevices;
+
+  for (int i = 0; i < 4; i++)
+    {
+      NetDeviceContainer link = csma.Install (NodeContainer (terminals.Get (i), csmaSwitch));
+      terminalDevices.Add (link.Get (0));
+      switchDevices.Add (link.Get (1));
+    }
+
+  // Create the bridge netdevice, which will do the packet switching
+  Ptr<Node> switchNode = csmaSwitch.Get (0);
+  BridgeHelper bridge;
+  bridge.Install (switchNode, switchDevices);
+
+  InternetStackHelper internet;
+  internet.Install (terminals);
+
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  ipv4.Assign (terminalDevices);
+
+  uint16_t port = 9;   // Discard port (RFC 863)
+
+  // Create the OnOff application to send UDP datagrams from n0 to n1.
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+                     Address (InetSocketAddress (Ipv4Address ("10.1.1.2"), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer app = onoff.Install (terminals.Get (0));
+  app.Start (Seconds (1.0));
+  app.Stop (Seconds (10.0));
+
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+                         Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  app = sink.Install (terminals.Get (1));
+  app.Start (Seconds (0.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBridgeTestCase::SinkRx, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Bridge should have passed 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaBroadcastTestCase : public TestCase
+{
+public:
+  CsmaBroadcastTestCase ();
+  virtual ~CsmaBroadcastTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRxNode1 (Ptr<const Packet> p, const Address &ad);
+  void SinkRxNode2 (Ptr<const Packet> p, const Address &ad);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_countNode1;
+  uint32_t m_countNode2;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaBroadcastTestCase::CsmaBroadcastTestCase ()
+  : TestCase ("Broadcast example for Carrier Sense Multiple Access (CSMA) networks"), m_countNode1 (0), m_countNode2 (0), m_drops (0)
+{
+}
+
+CsmaBroadcastTestCase::~CsmaBroadcastTestCase ()
+{
+}
+
+void 
+CsmaBroadcastTestCase::SinkRxNode1 (Ptr<const Packet> p, const Address &ad)
+{
+  m_countNode1++;
+}
+
+void 
+CsmaBroadcastTestCase::SinkRxNode2 (Ptr<const Packet> p, const Address &ad)
+{
+  m_countNode2++;
+}
+
+void 
+CsmaBroadcastTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+//
+// Example of the sending of a datagram to a broadcast address
+//
+// Network topology
+//     ==============
+//       |          |
+//       n0    n1   n2   
+//       |     |       
+//     ==========
+//
+//   n0 originates UDP broadcast to 255.255.255.255/discard port, which 
+//   is replicated and received on both n1 and n2
+//
+bool
+CsmaBroadcastTestCase::DoRun (void)
+{
+  NodeContainer c;
+  c.Create (3);
+  NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1));
+  NodeContainer c1 = NodeContainer (c.Get (0), c.Get (2));
+
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate(5000000)));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds(2)));
+
+  NetDeviceContainer n0 = csma.Install (c0);
+  NetDeviceContainer n1 = csma.Install (c1);
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.0.0", "255.255.255.0");
+  ipv4.Assign (n0);
+  ipv4.SetBase ("192.168.1.0", "255.255.255.0");
+  ipv4.Assign (n1);
+
+
+  // RFC 863 discard port ("9") indicates packet should be thrown away
+  // by the system.  We allow this silent discard to be overridden
+  // by the PacketSink application.
+  uint16_t port = 9;
+
+  // Create the OnOff application to send UDP datagrams from n0.
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+    Address (InetSocketAddress (Ipv4Address ("255.255.255.255"), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer app = onoff.Install (c0.Get (0));
+  // Start the application
+  app.Start (Seconds (1.0));
+  app.Stop (Seconds (10.0));
+
+  // Create an optional packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  app = sink.Install (c0.Get (1));
+  app.Add (sink.Install (c1.Get (1)));
+  app.Start (Seconds (1.0));
+  app.Stop (Seconds (10.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBroadcastTestCase::SinkRxNode1, this));
+  Config::ConnectWithoutContext ("/NodeList/2/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaBroadcastTestCase::SinkRxNode2, this));
+
+  Simulator::Run ();    
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_countNode1, 10, "Node 1 should have received 10 packets");
+  NS_TEST_ASSERT_MSG_EQ (m_countNode2, 10, "Node 2 should have received 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaMulticastTestCase : public TestCase
+{
+public:
+  CsmaMulticastTestCase ();
+  virtual ~CsmaMulticastTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (Ptr<const Packet> p, const Address &ad);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_count;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaMulticastTestCase::CsmaMulticastTestCase ()
+  : TestCase ("Multicast example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaMulticastTestCase::~CsmaMulticastTestCase ()
+{
+}
+
+void 
+CsmaMulticastTestCase::SinkRx (Ptr<const Packet> p, const Address& ad)
+{
+  m_count++;
+}
+
+void 
+CsmaMulticastTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+// Network topology
+//
+//                     Lan1
+//                 ===========
+//                 |    |    | 
+//       n0   n1   n2   n3   n4
+//       |    |    |
+//       ===========
+//           Lan0
+//
+// - Multicast source is at node n0;
+// - Multicast forwarded by node n2 onto LAN1;
+// - Nodes n0, n1, n2, n3, and n4 receive the multicast frame.
+// - Node n4 listens for the data 
+//
+bool
+CsmaMulticastTestCase::DoRun (void)
+{
+  //
+  // Set up default values for the simulation.  
+  //
+  // Select DIX/Ethernet II-style encapsulation (no LLC/Snap header)
+  Config::SetDefault ("ns3::CsmaNetDevice::EncapsulationMode", StringValue ("Dix"));  
+
+  NodeContainer c;
+  c.Create (5);
+  // We will later want two subcontainers of these nodes, for the two LANs
+  NodeContainer c0 = NodeContainer (c.Get (0), c.Get (1), c.Get (2));
+  NodeContainer c1 = NodeContainer (c.Get (2), c.Get (3), c.Get (4));
+  
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+ 
+  // We will use these NetDevice containers later, for IP addressing
+  NetDeviceContainer nd0 = csma.Install (c0);  // First LAN
+  NetDeviceContainer nd1 = csma.Install (c1);  // Second LAN
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  Ipv4AddressHelper ipv4Addr;
+  ipv4Addr.SetBase ("10.1.1.0", "255.255.255.0");
+  ipv4Addr.Assign (nd0);
+  ipv4Addr.SetBase ("10.1.2.0", "255.255.255.0");
+  ipv4Addr.Assign (nd1);
+
+  //
+  // Now we can configure multicasting.  As described above, the multicast 
+  // source is at node zero, which we assigned the IP address of 10.1.1.1 
+  // earlier.  We need to define a multicast group to send packets to.  This
+  // can be any multicast address from 224.0.0.0 through 239.255.255.255
+  // (avoiding the reserved routing protocol addresses).  
+  //
+
+  Ipv4Address multicastSource ("10.1.1.1");
+  Ipv4Address multicastGroup ("225.1.2.4");
+
+  // Now, we will set up multicast routing.  We need to do three things:
+  // 1) Configure a (static) multicast route on node n2
+  // 2) Set up a default multicast route on the sender n0 
+  // 3) Have node n4 join the multicast group
+  // We have a helper that can help us with static multicast
+  Ipv4StaticRoutingHelper multicast;
+
+  // 1) Configure a (static) multicast route on node n2 (multicastRouter)
+  Ptr<Node> multicastRouter = c.Get (2);  // The node in question
+  Ptr<NetDevice> inputIf = nd0.Get (2);  // The input NetDevice
+  NetDeviceContainer outputDevices;  // A container of output NetDevices
+  outputDevices.Add (nd1.Get (0));  // (we only need one NetDevice here)
+
+  multicast.AddMulticastRoute (multicastRouter, multicastSource, 
+    multicastGroup, inputIf, outputDevices);
+  
+  // 2) Set up a default multicast route on the sender n0 
+  Ptr<Node> sender = c.Get (0);
+  Ptr<NetDevice> senderIf = nd0.Get(0);
+  multicast.SetDefaultMulticastRoute (sender, senderIf);
+
+  //
+  // Create an OnOff application to send UDP datagrams from node zero to the
+  // multicast group (node four will be listening).
+  //
+
+  uint16_t multicastPort = 9;   // Discard port (RFC 863)
+
+  // Configure a multicast packet generator.
+  //
+  // Make packets be sent about every defaultPacketSize / dataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+    Address (InetSocketAddress (multicastGroup, multicastPort)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer srcC = onoff.Install (c0.Get (0));
+
+  //
+  // Tell the application when to start and stop.
+  //
+  srcC.Start(Seconds(1.));
+  srcC.Stop (Seconds(10.));
+
+  // Create an optional packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+                         InetSocketAddress (Ipv4Address::GetAny(), multicastPort));
+
+  ApplicationContainer sinkC = sink.Install (c1.Get (2)); // Node n4 
+  // Start the sink
+  sinkC.Start (Seconds (1.0));
+  sinkC.Stop (Seconds (10.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/4/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaMulticastTestCase::SinkRx, this));
+
+  //
+  // Now, do the actual simulation.
+  //
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 4 should have received 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaOneSubnetTestCase : public TestCase
+{
+public:
+  CsmaOneSubnetTestCase ();
+  virtual ~CsmaOneSubnetTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRxNode0 (Ptr<const Packet> p, const Address &ad);
+  void SinkRxNode1 (Ptr<const Packet> p, const Address &ad);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_countNode0;
+  uint32_t m_countNode1;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaOneSubnetTestCase::CsmaOneSubnetTestCase ()
+  : TestCase ("One subnet example for Carrier Sense Multiple Access (CSMA) networks"), m_countNode0 (0), m_countNode1 (0), m_drops (0)
+{
+}
+
+CsmaOneSubnetTestCase::~CsmaOneSubnetTestCase ()
+{
+}
+
+void 
+CsmaOneSubnetTestCase::SinkRxNode0 (Ptr<const Packet> p, const Address &ad)
+{
+  m_countNode0++;
+}
+
+void 
+CsmaOneSubnetTestCase::SinkRxNode1 (Ptr<const Packet> p, const Address &ad)
+{
+  m_countNode1++;
+}
+
+void 
+CsmaOneSubnetTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//       =================
+//              LAN
+//
+// - CBR/UDP flows from n0 to n1 and from n3 to n0
+// - DropTail queues 
+//
+bool
+CsmaOneSubnetTestCase::DoRun (void)
+{
+  NodeContainer nodes;
+  nodes.Create (4);
+
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+  //
+  // Now fill out the topology by creating the net devices required to connect
+  // the nodes to the channels and hooking them up.
+  //
+  NetDeviceContainer devices = csma.Install (nodes);
+
+  InternetStackHelper internet;
+  internet.Install (nodes);
+
+  // We've got the "hardware" in place.  Now we need to add IP addresses.
+  //
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer interfaces = ipv4.Assign (devices);
+
+  uint16_t port = 9;   // Discard port (RFC 863)
+
+  //
+  // Create an OnOff application to send UDP datagrams from node zero
+  // to node 1.
+  //
+  // Make packets be sent about every defaultPacketSize / dataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+                     Address (InetSocketAddress (interfaces.GetAddress (1), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer app = onoff.Install (nodes.Get (0));
+  // Start the application
+  app.Start (Seconds (1.0));
+  app.Stop (Seconds (10.0));
+
+  // Create an optional packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  app = sink.Install (nodes.Get (1));
+  app.Start (Seconds (0.0));
+
+  // 
+  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+  //
+  onoff.SetAttribute ("Remote", 
+                      AddressValue (InetSocketAddress (interfaces.GetAddress (0), port)));
+  app = onoff.Install (nodes.Get (3));
+  app.Start(Seconds (1.1));
+  app.Stop (Seconds (10.0));
+
+  app = sink.Install (nodes.Get (0));
+  app.Start (Seconds (0.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/0/ApplicationList/1/$ns3::PacketSink/Rx", MakeCallback (&CsmaOneSubnetTestCase::SinkRxNode0, this));
+  Config::ConnectWithoutContext ("/NodeList/1/ApplicationList/0/$ns3::PacketSink/Rx", MakeCallback (&CsmaOneSubnetTestCase::SinkRxNode1, this));
+
+  //
+  // Now, do the actual simulation.
+  //
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_countNode0, 10, "Node 0 should have received 10 packets");
+  NS_TEST_ASSERT_MSG_EQ (m_countNode1, 10, "Node 1 should have received 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaPacketSocketTestCase : public TestCase
+{
+public:
+  CsmaPacketSocketTestCase ();
+  virtual ~CsmaPacketSocketTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (std::string path, Ptr<const Packet> p, const Address &address);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_count;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaPacketSocketTestCase::CsmaPacketSocketTestCase ()
+  : TestCase ("Packet socket example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaPacketSocketTestCase::~CsmaPacketSocketTestCase ()
+{
+}
+
+void 
+CsmaPacketSocketTestCase::SinkRx (std::string path, Ptr<const Packet> p, const Address& address)
+{
+  m_count++;
+}
+
+void 
+CsmaPacketSocketTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+//
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - Packet socket flow from n0 to n1 and from node n3 to n0
+// -- We will test reception at node n0
+// - Default 512 byte packets generated by traffic generator
+//
+bool
+CsmaPacketSocketTestCase::DoRun (void)
+{
+  // Here, we will explicitly create four nodes.
+  NodeContainer nodes;
+  nodes.Create (4);
+
+  PacketSocketHelper packetSocket;
+  packetSocket.Install (nodes);
+
+  // create the shared medium used by all csma devices.
+  Ptr<CsmaChannel> channel = CreateObjectWithAttributes<CsmaChannel> (
+    "DataRate", DataRateValue (DataRate(5000000)), 
+    "Delay", TimeValue (MilliSeconds(2)));
+
+  // use a helper function to connect our nodes to the shared channel.
+  CsmaHelper csma;
+  csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+  NetDeviceContainer devs = csma.Install (nodes, channel);
+
+  // Create the OnOff application to send raw datagrams
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  PacketSocketAddress socket;
+  socket.SetSingleDevice(devs.Get (0)->GetIfIndex ());
+  socket.SetPhysicalAddress (devs.Get (1)->GetAddress ());
+  socket.SetProtocol (2);
+  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+  ApplicationContainer apps = onoff.Install (nodes.Get (0));
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  socket.SetSingleDevice (devs.Get (3)->GetIfIndex ());
+  socket.SetPhysicalAddress (devs.Get (0)->GetAddress ());
+  socket.SetProtocol (3);
+  onoff.SetAttribute ("Remote", AddressValue (socket));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+  apps = onoff.Install (nodes.Get (3));
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  PacketSinkHelper sink = PacketSinkHelper ("ns3::PacketSocketFactory",
+                                            socket);
+  apps = sink.Install (nodes.Get (0));
+  apps.Start (Seconds (0.0));
+  apps.Stop (Seconds (20.0));
+
+  // Trace receptions
+  Config::Connect ("/NodeList/0/ApplicationList/*/$ns3::PacketSink/Rx",
+                   MakeCallback (&CsmaPacketSocketTestCase::SinkRx, this));
+ 
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have received 10 packets on node 0
+  NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 0 should have received 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaPingTestCase : public TestCase
+{
+public:
+  CsmaPingTestCase ();
+  virtual ~CsmaPingTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (Ptr<const Packet> p, const Address &ad);
+  void PingRtt (std::string context, Time rtt);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_countSinkRx;
+  uint32_t m_countPingRtt;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaPingTestCase::CsmaPingTestCase ()
+  : TestCase ("Ping example for Carrier Sense Multiple Access (CSMA) networks"), m_countSinkRx (0), m_countPingRtt (0), m_drops (0)
+{
+}
+
+CsmaPingTestCase::~CsmaPingTestCase ()
+{
+}
+
+void 
+CsmaPingTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+  m_countSinkRx++;
+}
+
+void 
+CsmaPingTestCase::PingRtt (std::string context, Time rtt)
+{
+  m_countPingRtt++;
+}
+
+void 
+CsmaPingTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+//  node n0,n1,n3 pings to node n2
+//  node n0 generates protocol 2 (IGMP) to node n3
+//
+bool
+CsmaPingTestCase::DoRun (void)
+{
+  // Here, we will explicitly create four nodes.
+  NodeContainer c;
+  c.Create (4);
+
+  // connect all our nodes to a shared channel.
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+  csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+  NetDeviceContainer devs = csma.Install (c);
+
+  // add an ip stack to all nodes.
+  InternetStackHelper ipStack;
+  ipStack.Install (c);
+
+  // assign ip addresses
+  Ipv4AddressHelper ip;
+  ip.SetBase ("192.168.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer addresses = ip.Assign (devs);
+
+  // Create the OnOff application to send UDP datagrams from n0 to n1.
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  Config::SetDefault ("ns3::Ipv4RawSocketImpl::Protocol", StringValue ("2"));
+  InetSocketAddress dst = InetSocketAddress (addresses.GetAddress (3));
+  OnOffHelper onoff = OnOffHelper ("ns3::Ipv4RawSocketFactory", dst);
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer apps = onoff.Install (c.Get (0));
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  PacketSinkHelper sink = PacketSinkHelper ("ns3::Ipv4RawSocketFactory", dst);
+  apps = sink.Install (c.Get (3));
+  apps.Start (Seconds (0.0));
+  apps.Stop (Seconds (11.0));
+
+  V4PingHelper ping = V4PingHelper (addresses.GetAddress (2));
+  NodeContainer pingers;
+  pingers.Add (c.Get (0));
+  pingers.Add (c.Get (1));
+  pingers.Add (c.Get (3));
+  apps = ping.Install (pingers);
+  apps.Start (Seconds (2.0));
+  apps.Stop (Seconds (5.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx", 
+                                 MakeCallback (&CsmaPingTestCase::SinkRx, this));
+
+  // Trace pings
+  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::V4Ping/Rtt",
+                   MakeCallback (&CsmaPingTestCase::PingRtt, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_countSinkRx, 10, "Node 3 should have received 10 packets");
+
+  // We should have 3 pingers that ping every second for 3 seconds.
+  NS_TEST_ASSERT_MSG_EQ (m_countPingRtt, 9, "Node 2 should have been pinged 9 times");
+
+  return GetErrorStatus ();
+}
+
+class CsmaRawIpSocketTestCase : public TestCase
+{
+public:
+  CsmaRawIpSocketTestCase ();
+  virtual ~CsmaRawIpSocketTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (Ptr<const Packet> p, const Address &ad);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_count;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaRawIpSocketTestCase::CsmaRawIpSocketTestCase ()
+  : TestCase ("Raw internet protocol socket example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaRawIpSocketTestCase::~CsmaRawIpSocketTestCase ()
+{
+}
+
+void 
+CsmaRawIpSocketTestCase::SinkRx (Ptr<const Packet> p, const Address &ad)
+{
+  m_count++;
+}
+
+void 
+CsmaRawIpSocketTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+//
+// Network topology
+//    (sender)         (receiver)
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// Node n0 sends data to node n3 over a raw IP socket.  The protocol
+// number used is 2.
+//
+bool
+CsmaRawIpSocketTestCase::DoRun (void)
+{
+  // Here, we will explicitly create four nodes.
+  NodeContainer c;
+  c.Create (4);
+
+  // connect all our nodes to a shared channel.
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", DataRateValue (DataRate (5000000)));
+  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
+  csma.SetDeviceAttribute ("EncapsulationMode", StringValue ("Llc"));
+  NetDeviceContainer devs = csma.Install (c);
+
+  // add an ip stack to all nodes.
+  InternetStackHelper ipStack;
+  ipStack.Install (c);
+
+  // assign ip addresses
+  Ipv4AddressHelper ip;
+  ip.SetBase ("192.168.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer addresses = ip.Assign (devs);
+
+  // IP protocol configuration
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  Config::SetDefault ("ns3::Ipv4RawSocketImpl::Protocol", StringValue ("2"));
+  InetSocketAddress dst = InetSocketAddress (addresses.GetAddress (3));
+  OnOffHelper onoff = OnOffHelper ("ns3::Ipv4RawSocketFactory", dst);
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1.0)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0.0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer apps = onoff.Install (c.Get (0));
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  PacketSinkHelper sink = PacketSinkHelper ("ns3::Ipv4RawSocketFactory", dst);
+  apps = sink.Install (c.Get (3));
+  apps.Start (Seconds (0.0));
+  apps.Stop (Seconds (12.0));
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx", 
+                                 MakeCallback (&CsmaRawIpSocketTestCase::SinkRx, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // We should have sent and received 10 packets
+  NS_TEST_ASSERT_MSG_EQ (m_count, 10, "Node 3 should have received 10 packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaStarTestCase : public TestCase
+{
+public:
+  CsmaStarTestCase ();
+  virtual ~CsmaStarTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void SinkRx (Ptr<const Packet> p, const Address &ad);
+  void DropEvent (Ptr<const Packet> p);
+  uint32_t m_count;
+  uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+CsmaStarTestCase::CsmaStarTestCase ()
+  : TestCase ("Star example for Carrier Sense Multiple Access (CSMA) networks"), m_count (0), m_drops (0)
+{
+}
+
+CsmaStarTestCase::~CsmaStarTestCase ()
+{
+}
+
+void 
+CsmaStarTestCase::SinkRx (Ptr<const Packet> p, const Address& ad)
+{
+  m_count++;
+}
+
+void 
+CsmaStarTestCase::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+// Network topology (default)
+//
+//            n2     +          +     n3          .
+//             | ... |\        /| ... |           .
+//             ======= \      / =======           .
+//              CSMA    \    /   CSMA             .
+//                       \  /                     .
+//            n1     +--- n0 ---+     n4          .
+//             | ... |   /  \   | ... |           .
+//             =======  /    \  =======           .
+//              CSMA   /      \  CSMA             .
+//                    /        \                  .
+//            n6     +          +     n5          .
+//             | ... |          | ... |           .
+//             =======          =======           .
+//              CSMA             CSMA             .
+//
+bool
+CsmaStarTestCase::DoRun (void)
+{
+  //
+  // Default number of nodes in the star.
+  //
+  uint32_t nSpokes = 7;
+
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps"));
+  csma.SetChannelAttribute ("Delay", StringValue ("1ms"));
+  CsmaStarHelper star (nSpokes, csma);
+
+  NodeContainer fillNodes;
+
+  //
+  // Just to be nasy, hang some more nodes off of the CSMA channel for each
+  // spoke, so that there are a total of 16 nodes on each channel.  Stash
+  // all of these new devices into a container.
+  //
+  NetDeviceContainer fillDevices;
+
+  uint32_t nFill = 14;
+  for (uint32_t i = 0; i < star.GetSpokeDevices ().GetN (); ++i)
+    {
+      Ptr<Channel> channel = star.GetSpokeDevices ().Get (i)->GetChannel ();
+      Ptr<CsmaChannel> csmaChannel = channel->GetObject<CsmaChannel> ();
+      NodeContainer newNodes;
+      newNodes.Create (nFill);
+      fillNodes.Add (newNodes);
+      fillDevices.Add (csma.Install (newNodes, csmaChannel));
+    }
+
+  InternetStackHelper internet;
+  star.InstallStack (internet);
+  internet.Install (fillNodes);
+
+  star.AssignIpv4Addresses (Ipv4AddressHelper ("10.1.0.0", "255.255.255.0"));
+
+  //
+  // We assigned addresses to the logical hub and the first "drop" of the 
+  // CSMA network that acts as the spoke, but we also have a number of fill
+  // devices (nFill) also hanging off the CSMA network.  We have got to 
+  // assign addresses to them as well.  We put all of the fill devices into
+  // a single device container, so the first nFill devices are associated
+  // with the channel connected to spokeDevices.Get (0), the second nFill
+  // devices afe associated with the channel connected to spokeDevices.Get (1)
+  // etc.
+  //
+  Ipv4AddressHelper address;
+  for(uint32_t i = 0; i < star.SpokeCount (); ++i)
+  {
+    std::ostringstream subnet;
+    subnet << "10.1." << i << ".0";
+      address.SetBase (subnet.str ().c_str (), "255.255.255.0", "0.0.0.3");
+
+    for (uint32_t j = 0; j < nFill; ++j)
+      {
+        address.Assign (fillDevices.Get (i * nFill + j));
+      }
+  }
+
+  //
+  // Create a packet sink on the star "hub" to receive packets.  
+  // 
+  uint16_t port = 50000;
+  Address hubLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
+  PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", hubLocalAddress);
+  ApplicationContainer hubApp = packetSinkHelper.Install (star.GetHub ());
+  hubApp.Start (Seconds (1.0));
+  hubApp.Stop (Seconds (10.0));
+
+  //
+  // Create OnOff applications to send TCP to the hub, one on each spoke node.
+  //
+  // Make packets be sent about every DefaultPacketSize / DataRate = 
+  // 4096 bits / (5000 bits/second) = 0.82 second.
+  OnOffHelper onOffHelper ("ns3::TcpSocketFactory", Address ());
+  onOffHelper.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onOffHelper.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onOffHelper.SetAttribute ("DataRate", DataRateValue (DataRate (5000)));
+
+  ApplicationContainer spokeApps;
+
+  for (uint32_t i = 0; i < star.SpokeCount (); ++i)
+    {
+      AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i), port));
+      onOffHelper.SetAttribute ("Remote", remoteAddress);
+      spokeApps.Add (onOffHelper.Install (star.GetSpokeNode (i)));
+    }
+
+  spokeApps.Start (Seconds (1.0));
+  spokeApps.Stop (Seconds (10.0));
+
+  //
+  // Because we are evil, we also add OnOff applications to send TCP to the hub 
+  // from the fill devices on each CSMA link.  The first nFill nodes in the 
+  // fillNodes container are on the CSMA network talking to the zeroth device
+  // on the hub node.  The next nFill nodes are on the CSMA network talking to
+  // the first device on the hub node, etc.  So the ith fillNode is associated
+  // with the hub address found on the (i / nFill)th device on the hub node.
+  //
+  ApplicationContainer fillApps;
+
+  for (uint32_t i = 0; i < fillNodes.GetN (); ++i)
+    {
+      AddressValue remoteAddress (InetSocketAddress (star.GetHubIpv4Address (i / nFill), port));
+      onOffHelper.SetAttribute ("Remote", remoteAddress);
+      fillApps.Add (onOffHelper.Install (fillNodes.Get (i)));
+    }
+
+  fillApps.Start (Seconds (1.0));
+  fillApps.Stop (Seconds (10.0));
+
+  //
+  // Turn on global static routing so we can actually be routed across the star.
+  //
+  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+  // Trace receptions
+  Config::ConnectWithoutContext ("/NodeList/0/ApplicationList/*/$ns3::PacketSink/Rx", 
+                                 MakeCallback (&CsmaStarTestCase::SinkRx, this));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // The hub node should have received 10 packets from the nFill + 1
+  // nodes on each spoke.
+  NS_TEST_ASSERT_MSG_EQ (m_count, 10 * ( nSpokes * (nFill + 1)), "Hub node did not receive the proper number of packets");
+
+  return GetErrorStatus ();
+}
+
+class CsmaSystemTestSuite : public TestSuite
+{
+public:
+  CsmaSystemTestSuite ();
+};
+
+CsmaSystemTestSuite::CsmaSystemTestSuite ()
+  : TestSuite ("csma-system", BVT)
+{
+  AddTestCase (new CsmaBridgeTestCase);
+  AddTestCase (new CsmaBroadcastTestCase);
+  AddTestCase (new CsmaMulticastTestCase);
+  AddTestCase (new CsmaOneSubnetTestCase);
+  AddTestCase (new CsmaPacketSocketTestCase);
+  AddTestCase (new CsmaPingTestCase);
+  AddTestCase (new CsmaRawIpSocketTestCase);
+  AddTestCase (new CsmaStarTestCase);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static CsmaSystemTestSuite csmaSystemTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/global-routing-test-suite.cc	Fri Oct 15 16:31:32 2010 -0700
@@ -0,0 +1,409 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+#include "ns3/boolean.h"
+#include "ns3/config.h"
+#include "ns3/csma-helper.h"
+#include "ns3/flow-monitor.h"
+#include "ns3/flow-monitor-helper.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-global-routing-helper.h"
+#include "ns3/ipv4-static-routing-helper.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/on-off-helper.h"
+#include "ns3/packet.h"
+#include "ns3/packet-sink-helper.h"
+#include "ns3/packet-sink.h"
+#include "ns3/packet-socket-helper.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/point-to-point-helper.h"
+#include "ns3/pointer.h"
+#include "ns3/random-variable.h"
+#include "ns3/simple-channel.h"
+#include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/uinteger.h"
+#include "ns3/ipv4-packet-info-tag.h"
+
+using namespace ns3;
+
+class DynamicGlobalRoutingTestCase : public TestCase
+{
+public:
+  DynamicGlobalRoutingTestCase ();
+  virtual ~DynamicGlobalRoutingTestCase ();
+
+private:
+  void SinkRx (std::string path, Ptr<const Packet> p, const Address &address);
+  void HandleRead (Ptr<Socket>);
+  virtual bool DoRun (void);
+  int m_count;
+  uint8_t m_firstInterface[16];
+  uint8_t m_secondInterface[16];
+};
+
+// Add some help text to this case to describe what it is intended to test
+DynamicGlobalRoutingTestCase::DynamicGlobalRoutingTestCase ()
+  : TestCase ("Dynamic global routing example"), m_count (0)
+{
+}
+
+DynamicGlobalRoutingTestCase::~DynamicGlobalRoutingTestCase ()
+{
+}
+
+void
+DynamicGlobalRoutingTestCase::SinkRx (std::string path, Ptr<const Packet> p, const Address& address)
+{
+  Ipv4PacketInfoTag tag;
+  bool found;
+  found = p->PeekPacketTag (tag);
+  uint8_t now = static_cast<uint8_t> (Simulator::Now ().GetSeconds ());
+  if (found)
+    {
+      ;
+    }
+  m_firstInterface[now]++;
+  m_count++;
+}
+
+void 
+DynamicGlobalRoutingTestCase::HandleRead (Ptr<Socket> socket)
+{
+  Ptr<Packet> packet;
+  Address from;
+  while (packet = socket->RecvFrom (from))
+    {
+      if (packet->GetSize() == 0)
+        { //EOF
+          break;
+        }
+      Ipv4PacketInfoTag tag;
+      bool found;
+      found = packet->PeekPacketTag (tag);
+      uint8_t now = static_cast<uint8_t> (Simulator::Now ().GetSeconds ());
+      if (found)
+        {
+          if (tag.GetRecvIf () == 1)
+            {
+              m_firstInterface[now]++;
+            }
+          if (tag.GetRecvIf () == 2)
+            {
+              m_secondInterface[now]++;
+            }
+          m_count++;
+        }
+    }
+}
+
+// Test derived from examples/routing/dynamic-global-routing.cc
+//
+// Network topology
+//
+//  n0
+//     \ p-p
+//      \          (shared csma/cd)
+//       n2 -------------------------n3
+//      /            |        | 
+//     / p-p        n4        n5 ---------- n6
+//   n1                             p-p
+//   |                                      |
+//   ----------------------------------------
+//                p-p
+//
+// Test that for node n6, the interface facing n5 receives packets at
+// times (1-2), (4-6), (8-10), (11-12), (14-16) and the interface
+// facing n1 receives packets at times (2-4), (6-8), (12-13)
+//
+bool
+DynamicGlobalRoutingTestCase::DoRun (void)
+{
+  // The below value configures the default behavior of global routing.
+  // By default, it is disabled.  To respond to interface events, set to true
+  Config::SetDefault ("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue (true));
+
+  NodeContainer c;
+  c.Create (7);
+  NodeContainer n0n2 = NodeContainer (c.Get (0), c.Get (2));
+  NodeContainer n1n2 = NodeContainer (c.Get (1), c.Get (2));
+  NodeContainer n5n6 = NodeContainer (c.Get (5), c.Get (6));
+  NodeContainer n1n6 = NodeContainer (c.Get (1), c.Get (6));
+  NodeContainer n2345 = NodeContainer (c.Get (2), c.Get (3), c.Get (4), c.Get (5));
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  // We create the channels first without any IP addressing information
+  PointToPointHelper p2p;
+  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
+  NetDeviceContainer d0d2 = p2p.Install (n0n2);
+  NetDeviceContainer d1d6 = p2p.Install (n1n6);
+
+  NetDeviceContainer d1d2 = p2p.Install (n1n2);
+
+  p2p.SetDeviceAttribute ("DataRate", StringValue ("1500kbps"));
+  p2p.SetChannelAttribute ("Delay", StringValue ("10ms"));
+  NetDeviceContainer d5d6 = p2p.Install (n5n6);
+
+  // We create the channels first without any IP addressing information
+  CsmaHelper csma;
+  csma.SetChannelAttribute ("DataRate", StringValue ("5Mbps"));
+  csma.SetChannelAttribute ("Delay", StringValue ("2ms"));
+  NetDeviceContainer d2345 = csma.Install (n2345);
+  
+  // Later, we add IP addresses.  
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  ipv4.Assign (d0d2);
+
+  ipv4.SetBase ("10.1.2.0", "255.255.255.0");
+  ipv4.Assign (d1d2);
+
+  ipv4.SetBase ("10.1.3.0", "255.255.255.0");
+  Ipv4InterfaceContainer i5i6 = ipv4.Assign (d5d6);
+
+  ipv4.SetBase ("10.250.1.0", "255.255.255.0");
+  ipv4.Assign (d2345);
+
+  ipv4.SetBase ("172.16.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer i1i6 = ipv4.Assign (d1d6);
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  uint16_t port = 9;   // Discard port (RFC 863)
+  OnOffHelper onoff ("ns3::UdpSocketFactory",
+                     InetSocketAddress (i5i6.GetAddress (1), port));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", StringValue ("2kbps"));
+  onoff.SetAttribute ("PacketSize", UintegerValue (50));
+
+  ApplicationContainer apps = onoff.Install (c.Get (1));
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  // Create a second OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  OnOffHelper onoff2 ("ns3::UdpSocketFactory",
+                     InetSocketAddress (i1i6.GetAddress (1), port));
+  onoff2.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff2.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff2.SetAttribute ("DataRate", StringValue ("2kbps"));
+  onoff2.SetAttribute ("PacketSize", UintegerValue (50));
+
+  ApplicationContainer apps2 = onoff2.Install (c.Get (1));
+  apps2.Start (Seconds (11.0));
+  apps2.Stop (Seconds (16.0));
+
+  // Create an optional packet sink to receive these packets
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> sink2 = Socket::CreateSocket (c.Get (6), tid);
+  sink2->Bind (Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  sink2->Listen ();
+  sink2->ShutdownSend ();
+
+  sink2->SetRecvPktInfo (true);
+  sink2->SetRecvCallback (MakeCallback(&DynamicGlobalRoutingTestCase::HandleRead, this));
+
+  Ptr<Node> n1 = c.Get (1);
+  Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4> ();
+  // The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
+  // then the next p2p is numbered 2
+  uint32_t ipv4ifIndex1 = 2;
+
+  // Trace receptions
+  Config::Connect ("/NodeList/6/ApplicationList/*/$ns3::PacketSink/Rx",
+                   MakeCallback (&DynamicGlobalRoutingTestCase::SinkRx, this));
+
+  Simulator::Schedule (Seconds (2),&Ipv4::SetDown,ipv41, ipv4ifIndex1);
+  Simulator::Schedule (Seconds (4),&Ipv4::SetUp,ipv41, ipv4ifIndex1);
+
+  Ptr<Node> n6 = c.Get (6);
+  Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4> ();
+  // The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
+  // then the next p2p is numbered 2
+  uint32_t ipv4ifIndex6 = 2;
+  Simulator::Schedule (Seconds (6),&Ipv4::SetDown,ipv46, ipv4ifIndex6);
+  Simulator::Schedule (Seconds (8),&Ipv4::SetUp,ipv46, ipv4ifIndex6);
+
+  Simulator::Schedule (Seconds (12),&Ipv4::SetDown,ipv41, ipv4ifIndex1);
+  Simulator::Schedule (Seconds (14),&Ipv4::SetUp,ipv41, ipv4ifIndex1);
+
+  Simulator::Run ();
+
+  NS_TEST_ASSERT_MSG_EQ (m_count, 68, "Dynamic global routing did not deliver all packets");
+// Test that for node n6, the interface facing n5 receives packets at
+// times (1-2), (4-6), (8-10), (11-12), (14-16) and the interface
+// facing n1 receives packets at times (2-4), (6-8), (12-13)
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[1], 4, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[2], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[3], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[4], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[5], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[6], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[7], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[8], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[9], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[10], 0, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[11], 4, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[12], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_secondInterface[13], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[14], 5, "Dynamic global routing did not deliver all packets");
+  NS_TEST_ASSERT_MSG_EQ (m_firstInterface[15], 5, "Dynamic global routing did not deliver all packets");
+  Simulator::Destroy ();
+
+  return GetErrorStatus ();
+}
+
+class GlobalRoutingSlash32TestCase : public TestCase
+{
+public:
+  GlobalRoutingSlash32TestCase ();
+  virtual ~GlobalRoutingSlash32TestCase ();
+
+private:
+  virtual bool DoRun (void);
+};
+
+// Add some help text to this case to describe what it is intended to test
+GlobalRoutingSlash32TestCase::GlobalRoutingSlash32TestCase ()
+  : TestCase ("Slash 32 global routing example")
+{
+}
+
+GlobalRoutingSlash32TestCase::~GlobalRoutingSlash32TestCase ()
+{
+}
+
+// Test program for this 3-router scenario, using global routing
+//
+// (a.a.a.a/32)A<--x.x.x.0/30-->B<--y.y.y.0/30-->C(c.c.c.c/32)
+//
+bool
+GlobalRoutingSlash32TestCase::DoRun (void)
+{
+  Ptr<Node> nA = CreateObject<Node> ();
+  Ptr<Node> nB = CreateObject<Node> ();
+  Ptr<Node> nC = CreateObject<Node> ();
+
+  NodeContainer c = NodeContainer (nA, nB, nC);
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  // Point-to-point links
+  NodeContainer nAnB = NodeContainer (nA, nB);
+  NodeContainer nBnC = NodeContainer (nB, nC);
+
+  // We create the channels first without any IP addressing information
+  PointToPointHelper p2p;
+  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
+  NetDeviceContainer dAdB = p2p.Install (nAnB);
+
+  NetDeviceContainer dBdC = p2p.Install (nBnC);;
+
+  Ptr<CsmaNetDevice> deviceA = CreateObject<CsmaNetDevice> ();
+  deviceA->SetAddress (Mac48Address::Allocate ());
+  nA->AddDevice (deviceA);
+
+  Ptr<CsmaNetDevice> deviceC = CreateObject<CsmaNetDevice> ();
+  deviceC->SetAddress (Mac48Address::Allocate ());
+  nC->AddDevice (deviceC);
+
+  // Later, we add IP addresses.  
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.252");
+  Ipv4InterfaceContainer iAiB = ipv4.Assign (dAdB);
+
+  ipv4.SetBase ("10.1.1.4", "255.255.255.252");
+  Ipv4InterfaceContainer iBiC = ipv4.Assign (dBdC);
+
+  Ptr<Ipv4> ipv4A = nA->GetObject<Ipv4> ();
+  Ptr<Ipv4> ipv4C = nC->GetObject<Ipv4> ();
+
+  int32_t ifIndexA = ipv4A->AddInterface (deviceA);
+  int32_t ifIndexC = ipv4C->AddInterface (deviceC);
+
+  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255"));
+  ipv4A->AddAddress (ifIndexA, ifInAddrA);
+  ipv4A->SetMetric (ifIndexA, 1);
+  ipv4A->SetUp (ifIndexA);
+
+  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255"));
+  ipv4C->AddAddress (ifIndexC, ifInAddrC);
+  ipv4C->SetMetric (ifIndexC, 1);
+  ipv4C->SetUp (ifIndexC);
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  uint16_t port = 9;   // Discard port (RFC 863)
+  OnOffHelper onoff ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (ifInAddrC.GetLocal(), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000)));
+  ApplicationContainer apps = onoff.Install (nA);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  // Create a packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  apps = sink.Install (nC);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  Simulator::Run ();
+  // Check that we received 13 * 512 = 6656 bytes
+  Ptr<PacketSink> sinkPtr = DynamicCast <PacketSink> (apps.Get (0));
+  NS_TEST_ASSERT_MSG_EQ (sinkPtr->GetTotalRx (), 6656, "Static routing with /32 did not deliver all packets");
+  Simulator::Destroy ();
+
+  return GetErrorStatus ();
+}
+
+
+class GlobalRoutingTestSuite : public TestSuite
+{
+public:
+  GlobalRoutingTestSuite ();
+};
+
+GlobalRoutingTestSuite::GlobalRoutingTestSuite ()
+  : TestSuite ("global-routing", BVT)
+{
+  AddTestCase (new DynamicGlobalRoutingTestCase);
+  AddTestCase (new GlobalRoutingSlash32TestCase);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static GlobalRoutingTestSuite globalRoutingTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/static-routing-test-suite.cc	Fri Oct 15 16:31:32 2010 -0700
@@ -0,0 +1,175 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+// End-to-end tests for Ipv4 static routing
+
+#include "ns3/boolean.h"
+#include "ns3/config.h"
+#include "ns3/csma-helper.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/ipv4-static-routing-helper.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/on-off-helper.h"
+#include "ns3/packet.h"
+#include "ns3/packet-sink-helper.h"
+#include "ns3/packet-sink.h"
+#include "ns3/packet-socket-helper.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/point-to-point-helper.h"
+#include "ns3/pointer.h"
+#include "ns3/random-variable.h"
+#include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/test.h"
+#include "ns3/uinteger.h"
+
+using namespace ns3;
+
+class StaticRoutingSlash32TestCase : public TestCase
+{
+public:
+  StaticRoutingSlash32TestCase ();
+  virtual ~StaticRoutingSlash32TestCase ();
+
+private:
+  virtual bool DoRun (void);
+};
+
+// Add some help text to this case to describe what it is intended to test
+StaticRoutingSlash32TestCase::StaticRoutingSlash32TestCase ()
+  : TestCase ("Slash 32 static routing example")
+{
+}
+
+StaticRoutingSlash32TestCase::~StaticRoutingSlash32TestCase ()
+{
+}
+
+// Test program for this 3-router scenario, using static routing
+//
+// (a.a.a.a/32)A<--x.x.x.0/30-->B<--y.y.y.0/30-->C(c.c.c.c/32)
+//
+bool
+StaticRoutingSlash32TestCase::DoRun (void)
+{
+  Ptr<Node> nA = CreateObject<Node> ();
+  Ptr<Node> nB = CreateObject<Node> ();
+  Ptr<Node> nC = CreateObject<Node> ();
+
+  NodeContainer c = NodeContainer (nA, nB, nC);
+
+  InternetStackHelper internet;
+  internet.Install (c);
+
+  // Point-to-point links
+  NodeContainer nAnB = NodeContainer (nA, nB);
+  NodeContainer nBnC = NodeContainer (nB, nC);
+
+  // We create the channels first without any IP addressing information
+  PointToPointHelper p2p;
+  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
+  NetDeviceContainer dAdB = p2p.Install (nAnB);
+
+  NetDeviceContainer dBdC = p2p.Install (nBnC);;
+  
+  Ptr<CsmaNetDevice> deviceA = CreateObject<CsmaNetDevice> ();
+  deviceA->SetAddress (Mac48Address::Allocate ());
+  nA->AddDevice (deviceA);
+
+  Ptr<CsmaNetDevice> deviceC = CreateObject<CsmaNetDevice> ();
+  deviceC->SetAddress (Mac48Address::Allocate ());
+  nC->AddDevice (deviceC);
+
+  // Later, we add IP addresses.  
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.252");
+  Ipv4InterfaceContainer iAiB = ipv4.Assign (dAdB);
+
+  ipv4.SetBase ("10.1.1.4", "255.255.255.252");
+  Ipv4InterfaceContainer iBiC = ipv4.Assign (dBdC);
+
+  Ptr<Ipv4> ipv4A = nA->GetObject<Ipv4> ();
+  Ptr<Ipv4> ipv4B = nB->GetObject<Ipv4> ();
+  Ptr<Ipv4> ipv4C = nC->GetObject<Ipv4> ();
+  
+  int32_t ifIndexA = ipv4A->AddInterface (deviceA);
+  int32_t ifIndexC = ipv4C->AddInterface (deviceC);
+    
+  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("/32"));
+  ipv4A->AddAddress (ifIndexA, ifInAddrA);
+  ipv4A->SetMetric (ifIndexA, 1);
+  ipv4A->SetUp (ifIndexA);
+
+  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("/32"));
+  ipv4C->AddAddress (ifIndexC, ifInAddrC);
+  ipv4C->SetMetric (ifIndexC, 1);
+  ipv4C->SetUp (ifIndexC);
+ 
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  // Create static routes from A to C
+  Ptr<Ipv4StaticRouting> staticRoutingA = ipv4RoutingHelper.GetStaticRouting (ipv4A);
+  // The ifIndex for this outbound route is 1; the first p2p link added
+  staticRoutingA->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.2"), 1);
+  Ptr<Ipv4StaticRouting> staticRoutingB = ipv4RoutingHelper.GetStaticRouting (ipv4B);
+  // The ifIndex we want on node B is 2; 0 corresponds to loopback, and 1 to the first point to point link
+  staticRoutingB->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"), 2);
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  uint16_t port = 9;   // Discard port (RFC 863)
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+    Address (InetSocketAddress (ifInAddrC.GetLocal (), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000)));
+  ApplicationContainer apps = onoff.Install (nA);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  // Create a packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  apps = sink.Install (nC);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  Simulator::Run ();
+  // Check that we received 13 * 512 = 6656 bytes
+  Ptr<PacketSink> sinkPtr = DynamicCast <PacketSink> (apps.Get (0));
+  NS_TEST_ASSERT_MSG_EQ (sinkPtr->GetTotalRx (), 6656, "Static routing with /32 did not deliver all packets");
+  Simulator::Destroy ();
+
+  return GetErrorStatus ();
+}
+
+class StaticRoutingTestSuite : public TestSuite
+{
+public:
+  StaticRoutingTestSuite ();
+};
+
+StaticRoutingTestSuite::StaticRoutingTestSuite ()
+  : TestSuite ("static-routing", BVT)
+{
+  AddTestCase (new StaticRoutingSlash32TestCase);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static StaticRoutingTestSuite staticRoutingTestSuite;
--- a/src/test/wscript	Fri Oct 15 12:53:05 2010 -0700
+++ b/src/test/wscript	Fri Oct 15 16:31:32 2010 -0700
@@ -6,7 +6,10 @@
 def build(bld):
     test = bld.create_ns3_module('test', ['core'])
     test.source = [
+        'csma-system-test-suite.cc',
+        'global-routing-test-suite.cc',
         'sample-test-suite.cc',
+        'static-routing-test-suite.cc',
         'error-model-test-suite.cc',
         'mobility-test-suite.cc',
         ]
--- a/wscript	Fri Oct 15 12:53:05 2010 -0700
+++ b/wscript	Fri Oct 15 16:31:32 2010 -0700
@@ -43,7 +43,6 @@
 
 # local modules
 import wutils
-import regression
 
 Configure.autoconfig = 1
 
@@ -54,14 +53,6 @@
 wutils.VERSION = VERSION
 wutils.APPNAME = APPNAME
 
-#
-# The last part of the path name to use to find the regression traces.  The
-# path will be APPNAME + '-' + VERSION + REGRESSION_SUFFIX, e.g.,
-# ns-3-dev-ref-traces
-#
-REGRESSION_SUFFIX = "-ref-traces"
-
-
 # these variables are mandatory ('/' are converted automatically)
 srcdir = '.'
 blddir = 'build'
@@ -97,22 +88,6 @@
     shutil.rmtree("doc/latex", True)
     shutil.rmtree("nsc", True)
 
-    ## build the name of the traces subdirectory.  Will be something like
-    ## ns-3-dev-ref-traces
-    traces_name = APPNAME + '-' + VERSION + REGRESSION_SUFFIX
-    ## Create a tar.bz2 file with the traces
-    env = load_env()
-    regression_dir = env['REGRESSION_TRACES']
-    if not os.path.isdir(regression_dir):
-        Logs.warn("Not creating traces archive: the %s directory does not exist" % regression_dir)
-    else:
-        traceball = traces_name + wutils.TRACEBALL_SUFFIX
-        tar = tarfile.open(os.path.join("..", traceball), 'w:bz2')
-        files = get_files(regression_dir)
-        for fullfilename,relfilename in files:
-            tar.add(fullfilename,arcname=relfilename)
-        tar.close()
-
 def set_options(opt):
     # options provided by the modules
     opt.tool_options('compiler_cc')
@@ -177,23 +152,9 @@
     opt.add_option('--disable-examples',
                    help=('Do not build the ns-3 examples and samples.'),
                    dest='enable_examples', action='store_false')
-    opt.add_option('--regression',
-                   help=("Enable regression testing; only used for the 'check' target"),
-                   default=False, dest='regression', action="store_true")
     opt.add_option('--check',
                    help=('DEPRECATED (run ./test.py)'),
                    default=False, dest='check', action="store_true")
-    opt.add_option('--regression-generate',
-                   help=("Generate new regression test traces."),
-                   default=False, dest='regression_generate', action="store_true")
-    opt.add_option('--regression-tests',
-                   help=('For regression testing, only run/generate the indicated regression tests, '
-                         'specified as a comma separated list of test names'),
-                   dest='regression_tests', type="string")
-    opt.add_option('--with-regression-traces',
-                   help=('Path to the regression reference traces directory'),
-                   default=None,
-                   dest='regression_traces', type="string")
     opt.add_option('--enable-static',
                    help=('Compile NS-3 statically: works only on linux, without python'),
                    dest='enable_static', action='store_true',
@@ -258,20 +219,6 @@
         pass
     conf.check_tool('command', ['waf-tools'])
 
-    # Check for the location of regression reference traces
-    if Options.options.regression_traces is not None:
-        if os.path.isdir(Options.options.regression_traces):
-            conf.check_message("regression traces location", '', True, ("%s (given)" % Options.options.regression_traces))
-            conf.env['REGRESSION_TRACES'] = os.path.abspath(Options.options.regression_traces)
-    else:
-        traces = os.path.join('..', "%s-%s%s" % (APPNAME, VERSION, REGRESSION_SUFFIX))
-        if os.path.isdir(traces):
-            conf.check_message("regression reference traces", '', True, ("%s (guessed)" % traces))
-            conf.env['REGRESSION_TRACES'] = os.path.abspath(traces)
-        del traces
-    if not conf.env['REGRESSION_TRACES']:
-        conf.check_message("regression reference traces", '', False)
-
     # create the second environment, set the variant and set its name
     variant_env = conf.env.copy()
     variant_name = Options.options.build_profile
@@ -373,9 +320,6 @@
     conf.report_optional_feature("ENABLE_EXAMPLES", "Build examples and samples", env['ENABLE_EXAMPLES'], 
                                  why_not_examples)
 
-    # we cannot pull regression traces without mercurial
-    conf.find_program('hg', var='MERCURIAL')
-
     conf.find_program('valgrind', var='VALGRIND')
 
     env['ENABLE_STATIC_NS3'] = False
@@ -645,19 +589,6 @@
             if type(gen).__name__ in ['ns3header_taskgen', 'ns3moduleheader_taskgen']:
                 gen.post()
 
-    if Options.options.regression or Options.options.regression_generate:
-        regression_traces = env['REGRESSION_TRACES']
-        if not regression_traces:
-            raise Utils.WafError("Cannot run regression tests: reference traces directory not given"
-                                 " (--with-regression-traces configure option)")
-
-        if env['ENABLE_EXAMPLES'] == True:
-            regression.run_regression(bld, regression_traces)
-        else:
-            raise Utils.WafError("Cannot run regression tests: building the ns-3 examples is not enabled"
-                                 " (regression tests are based on examples)")
-
-
     if Options.options.doxygen_no_build:
         _doxygen(bld)
         raise SystemExit(0)
--- a/wutils.py	Fri Oct 15 12:53:05 2010 -0700
+++ b/wutils.py	Fri Oct 15 16:31:32 2010 -0700
@@ -19,13 +19,6 @@
 VERSION=None
 bld=None
 
-#
-# The last part of the path name to use to find the regression traces tarball.
-# path will be APPNAME + '-' + VERSION + REGRESSION_SUFFIX + TRACEBALL_SUFFIX,
-# e.g., ns-3-dev-ref-traces.tar.bz2
-#
-TRACEBALL_SUFFIX = ".tar.bz2"
-
 
 
 def get_command_template(env, arguments=()):