branch merge
authorCraig Dowell <craigdo@ee.washington.edu>
Mon, 28 Sep 2009 10:11:05 -0700
changeset 5274 8723fb3b377b
parent 5273 c95bd39cc980 (current diff)
parent 5272 867b0ba95374 (diff)
child 5275 d4008f2981ba
branch merge
samples/main-test.cc
test.py
--- a/doc/testing/how-to-write-tests.texi	Mon Sep 28 10:04:32 2009 -0700
+++ b/doc/testing/how-to-write-tests.texi	Mon Sep 28 10:11:05 2009 -0700
@@ -20,10 +20,30 @@
 we hope to cover some common cases that can be used as a guide to
 writing new tests.
 
+@section Sample TestSuite skeleton
+
+When starting from scratch (i.e. not adding a TestCase to an existing
+TestSuite), these things need to be decided up front:
+
+@itemize @bullet
+@item What the test suite will be called 
+@item What type of test it will be (Build Verification Test, Unit Test,
+System Test, or Performance Test)
+@item Where the test code will live (either in an existing ns-3 module or
+separately in src/test/ directory).  You will have to edit the wscript
+file in that directory to compile your new code, if it is a new file.
+@end itemize
+
+See the file @code{src/test/sample-test-suite.cc} and corresponding
+wscript file in that directory for a simple example, and see the directories
+under @code{src/test} for more complicated examples.
+
 @cartouche
 @emph{The rest of this chapter remains to be written}
 @end cartouche
 
+@section How to add an example program to the test suite
+
 @section Testing for boolean outcomes
 
 @section Testing outcomes when randomness is involved
--- a/examples/multirate.cc	Mon Sep 28 10:04:32 2009 -0700
+++ b/examples/multirate.cc	Mon Sep 28 10:11:05 2009 -0700
@@ -17,27 +17,36 @@
  */
 
 /**
- * Objective: Test multi-rate algorithms in varios scenarios and settings
+ * Scenarios: 100 nodes, multiple simultaneous flows, multi-hop ad hoc, routing,
+ * and mobility
  *
  * INSTRUCTIONS:
  *
+ * To optimize build: 
+ * ./waf -d optimized configure
+ * ./waf
+ *
  * To compile:
  * ./waf --run multirate
  *
- * To compile with command input:
+ * To compile with commandline(useful for varying parameters or configurations):
  * ./waf --run "scratch/multirate.cc --packetSize=2000 --totalTime=50"
  *
  * To turn on NS_LOG:
  * export NS_LOG=multirate=level_all
+ * (can only view log if built with ./waf -d debug configure)
  *
  * To debug:
- * /waf --shell
+ * ./waf --shell
  * gdb ./build/debug/scratch/multirate
  *
  * To view pcap files:
  * tcpdump -nn -tt -r filename.pcap
  *
- * Sidenote: Simulation might take sometime
+ * To monitor the files
+ * tail -f filename.pcap
+ *
+ * Sidenote: Simulation might take sometime 
  */
 
 #include "ns3/core-module.h"
@@ -58,37 +67,47 @@
 
 class Experiment
 {
-
 public:
 
   Experiment ();
   Experiment (std::string name);
   Gnuplot2dDataset Run (const WifiHelper &wifi, const YansWifiPhyHelper &wifiPhy,
                         const NqosWifiMacHelper &wifiMac, const YansWifiChannelHelper &wifiChannel, const MobilityHelper &mobility);
+
   bool CommandSetup (int argc, char **argv);
+  bool IsRouting () { return (enableRouting == 1) ? 1:0; }
+  bool IsMobility () { return (enableMobility == 1) ? 1:0; }
 
+  uint32_t GetScenario () {return scenario; }
+
+  std::string GetRtsThreshold () { return rtsThreshold; }
+  std::string GetOutputFileName () { return outputFileName; }
+  std::string GetRateManager () { return rateManager; }
+  
 private:
 
   Vector GetPosition (Ptr<Node> node);
   Ptr<Socket> SetupPacketReceive (Ptr<Node> node);
+  NodeContainer GenerateNeighbors(NodeContainer c, uint32_t senderId);
 
   void ApplicationSetup (Ptr<Node> client, Ptr<Node> server, double start, double stop);
   void AssignNeighbors (NodeContainer c);
   void SelectSrcDest (NodeContainer c);
   void ReceivePacket (Ptr<Socket> socket);
   void CheckThroughput ();
-  void SendMultiDestinations(Ptr<Node> sender, NodeContainer c);
+  void SendMultiDestinations (Ptr<Node> sender, NodeContainer c);
 
   Gnuplot2dDataset m_output;
 
-  uint32_t m_bytesTotal;
+  double totalTime; 
+
+  uint32_t bytesTotal;
   uint32_t packetSize;
   uint32_t gridSize; 
   uint32_t nodeDistance;
   uint32_t port;
   uint32_t expMean;
-
-  double totalTime; 
+  uint32_t scenario;
 
   bool enablePcap;
   bool enableTracing;
@@ -97,6 +116,7 @@
   bool enableMobility;
 
   NodeContainer containerA, containerB, containerC, containerD; 
+  std::string rtsThreshold, rateManager, outputFileName;
 };
 
 Experiment::Experiment ()
@@ -104,18 +124,22 @@
 
 Experiment::Experiment (std::string name) : 
   m_output (name),
-  m_bytesTotal(0),
+  totalTime (50), //use shorter time for faster simulation 
+  bytesTotal(0),
   packetSize (2000),
   gridSize (10), //10x10 grid  for a total of 100 nodes
-  nodeDistance (40),
+  nodeDistance (30),
   port (5000),
   expMean (4), //flows being exponentially distributed
-  totalTime (50),
-  enablePcap(false), // will flood the directory with *.pcap files
-  enableTracing(false),
-  enableFlowMon(true),
-  enableRouting(false),
-  enableMobility(false)
+  scenario (4), 
+  enablePcap (false), // will flood the directory with *.pcap files
+  enableTracing (true),
+  enableFlowMon (true),
+  enableRouting (false),
+  enableMobility (false),
+  rtsThreshold ("2200"), //0 for enabling rts/cts
+  rateManager ("ns3::MinstrelWifiManager"),
+  outputFileName ("minstrel")
 {
   m_output.SetStyle (Gnuplot2dDataset::LINES);
 }
@@ -138,15 +162,15 @@
   Ptr<Packet> packet;
   while (packet = socket->Recv ())
   {
-    m_bytesTotal += packet->GetSize();
+    bytesTotal += packet->GetSize();
   }
 }
 
 void
 Experiment::CheckThroughput()
 {
-  double mbs = ((m_bytesTotal * 8.0) /1000000);
-  m_bytesTotal = 0;
+  double mbs = ((bytesTotal * 8.0) /1000000);
+  bytesTotal = 0;
   m_output.Add ((Simulator::Now ()).GetSeconds (), mbs);
 
   Simulator::Schedule (Seconds (1.0), &Experiment::CheckThroughput, this);
@@ -203,6 +227,27 @@
 }
 
 /**
+ * Generate 1-hop and 2-hop neighbors of a node in grid topology
+ *
+ */
+NodeContainer
+Experiment::GenerateNeighbors (NodeContainer c, uint32_t senderId)
+{
+  NodeContainer nc;
+  uint32_t limit = senderId + 2;  
+  for (uint32_t i= senderId - 2; i <= limit; i++)
+    {
+      //must ensure the boundaries for other topologies
+      nc.Add(c.Get(i));
+      nc.Add(c.Get(i + 10));
+      nc.Add(c.Get(i + 20));
+      nc.Add(c.Get(i - 10));
+      nc.Add(c.Get(i - 20));
+    }
+  return nc;
+}
+
+/**
  * Sources and destinations are randomly selected such that a node 
  * may be the source for multiple destinations and a node maybe a destination 
  * for multiple sources. 
@@ -216,7 +261,7 @@
 
   for (uint32_t i=0; i < totalNodes/3; i++)
     {
-      ApplicationSetup (c.Get(uvSrc.GetValue()), c.Get(uvDest.GetValue()) ,  1, totalTime);
+      ApplicationSetup (c.Get(uvSrc.RandomVariable::GetInteger()), c.Get(uvDest.RandomVariable::GetInteger()) ,  1, totalTime);
     }
 }
 
@@ -297,8 +342,6 @@
   apps.Start (Seconds (start));
   apps.Stop (Seconds (stop));
 
-
-
 /*
   // Select either Sink Method 1 or 2 for setting up sink
   // one using a helper vs one without
@@ -380,29 +423,24 @@
   mobil.Install (c);
 
 
-
-  if (enableRouting)
-    {
-      SelectSrcDest(c);
-
-/*
-      //another setup
-      //All flows begin at the same time
-      for (uint32_t i = 0,j = 0; i < nodeSize - 1; i = i+2)
-        {
-          NS_LOG_DEBUG("Flow " << ++j);
-          ApplicationSetup (c.Get (i), c.Get (i+1),  1, totalTime);
-        }
-*/
-
 //    NS_LOG_INFO ("Enabling global routing on all nodes");
 //    Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
 
+  if ( scenario == 1 && enableRouting)
+    {
+      SelectSrcDest(c);
     }
-  else
+  else if ( scenario == 2)
+    {
+      //All flows begin at the same time
+      for (uint32_t i = 0; i < nodeSize - 1; i = i+2)
+        {
+          ApplicationSetup (c.Get (i), c.Get (i+1),  1, totalTime);
+        }
+    }
+  else if ( scenario == 3)
     {
       AssignNeighbors(c);
-
       //Note: these senders are hand-picked in order to ensure good coverage
       //for 10x10 grid, basically one sender for each quadrant
       //you might have to change these values for other grids 
@@ -418,19 +456,45 @@
       NS_LOG_DEBUG(">>>>>>>>>region D<<<<<<<<<");
       SendMultiDestinations(c.Get(76), containerD);
     }
+  else if ( scenario == 4)
+    {
+      //GenerateNeighbors(NodeContainer, uint32_t sender)
+      //Note: these senders are hand-picked in order to ensure good coverage
+      //you might have to change these values for other grids 
+      NodeContainer c1, c2, c3, c4, c5, c6, c7, c8, c9;
 
+      c1 = GenerateNeighbors(c, 22);
+      c2 = GenerateNeighbors(c, 24);;
+      c3 = GenerateNeighbors(c, 26);;
+      c4 = GenerateNeighbors(c, 42);;
+      c5 = GenerateNeighbors(c, 44);;
+      c6 = GenerateNeighbors(c, 46);;
+      c7 = GenerateNeighbors(c, 62);;
+      c8 = GenerateNeighbors(c, 64);;
+      c9 = GenerateNeighbors(c, 66);;
+
+      SendMultiDestinations(c.Get(22), c1);
+      SendMultiDestinations(c.Get(24), c2);
+      SendMultiDestinations(c.Get(26), c3);
+      SendMultiDestinations(c.Get(42), c4);
+      SendMultiDestinations(c.Get(44), c5);
+      SendMultiDestinations(c.Get(46), c6);
+      SendMultiDestinations(c.Get(62), c7);
+      SendMultiDestinations(c.Get(64), c8);
+      SendMultiDestinations(c.Get(66), c9);
+    }
 
   CheckThroughput ();
 
   if (enablePcap)
     {
-      phy.EnablePcapAll("multirate");
+      phy.EnablePcapAll(GetOutputFileName());
     }
 
   if (enableTracing)
     {
       std::ofstream ascii;
-      ascii.open ("multirate.tr");
+      ascii.open ((GetOutputFileName() + ".tr").c_str());
       phy.EnableAsciiAll (ascii);
     }
 
@@ -447,7 +511,7 @@
 
   if (enableFlowMon)
     {
-      flowmon->SerializeToXmlFile ("multirate.flowmon", false, false);
+      flowmon->SerializeToXmlFile ((GetOutputFileName() + ".flomon"), false, false);
     }
 
   Simulator::Destroy ();
@@ -462,6 +526,12 @@
   CommandLine cmd;
   cmd.AddValue ("packetSize", "packet size", packetSize);
   cmd.AddValue ("totalTime", "simulation time", totalTime);
+  cmd.AddValue ("rtsThreshold", "rts threshold", rtsThreshold);
+  cmd.AddValue ("rateManager", "type of rate", rateManager);
+  cmd.AddValue ("outputFileName", "output filename", outputFileName);
+  cmd.AddValue ("enableRouting", "enable Routing", enableRouting);
+  cmd.AddValue ("enableMobility", "enable Mobility", enableMobility);
+  cmd.AddValue ("scenario", "scenario ", scenario);
 
   cmd.Parse (argc, argv);
   return true;
@@ -469,17 +539,25 @@
 
 int main (int argc, char *argv[])
 {
-  std::ofstream outfile ("multirate.plt");
+
+  Experiment experiment;
+  experiment = Experiment ("multirate");
+
+  //for commandline input
+  if (!experiment.CommandSetup(argc, argv))
+    {
+      std::cout << "Configuration failed..." << std::endl;
+      exit(1);
+    }
 
   // disable fragmentation
+  // set value to 0 for enabling fragmentation
   Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
- 
-  //set value to 0 for enabling RTS/CTS
-  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue (experiment.GetRtsThreshold()));
+
+  std::ofstream outfile ((experiment.GetOutputFileName()+ ".plt").c_str());
 
   MobilityHelper mobility;
-  Experiment experiment;
-
   Gnuplot gnuplot;
   Gnuplot2dDataset dataset;
 
@@ -489,34 +567,21 @@
   YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
   Ssid ssid = Ssid ("Testbed");
   
-
   wifiMac.SetType ("ns3::AdhocWifiMac", "Ssid", SsidValue(ssid));
   wifi.SetStandard (WIFI_PHY_STANDARD_holland);
-
-
-
-  //To ensure repeatable experiment scenario
-  //for each multirate, please uncomment one at a time and obtain results 
-  experiment = Experiment ("minstrel");
-  //experiment = Experiment ("ideal");
+  wifi.SetRemoteStationManager (experiment.GetRateManager());
 
-  //for commandline input
-  if (!experiment.CommandSetup(argc, argv))
-    {
-      std::cout << "exiting ..." << std::endl;
-      exit(1);
-    }
+  //printing out selection confirmation
+  std::cout << "Scenario: " << experiment.GetScenario () << std::endl;
+  std::cout << "Rts Threshold: " << experiment.GetRtsThreshold() << std::endl;
+  std::cout << "Name:  " << experiment.GetOutputFileName() << std::endl;
+  std::cout << "Rate:  " << experiment.GetRateManager() << std::endl;
+  std::cout << "Routing: " << experiment.IsRouting() << std::endl;
+  std::cout << "Mobility: " << experiment.IsMobility() << std::endl;
 
-  wifi.SetRemoteStationManager ("ns3::MinstrelWifiManager");
   dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
+
   gnuplot.AddDataset (dataset);
-
-  /*
-  wifi.SetRemoteStationManager ("ns3::IdealWifiManager");
-  dataset = experiment.Run (wifi, wifiPhy, wifiMac, wifiChannel, mobility);
-  gnuplot.AddDataset (dataset);
-  */
-
   gnuplot.GenerateOutput (outfile);
 
   return 0;
--- a/samples/main-test.cc	Mon Sep 28 10:04:32 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-
-#include "ns3/test.h"
-
-using namespace ns3;
-
-#ifdef RUN_SELF_TESTS
-
-// declare subclass of base class Test
-class MyTest : public Test {
-public:
-  MyTest (bool ok);
-  virtual ~MyTest ();
-  virtual bool RunTests (void);
-private:
-  bool m_ok;
-};
-
-// implement MyTest
-MyTest::MyTest (bool ok)
-  : Test ("My"),
-    m_ok (ok)
-{}
-MyTest::~MyTest ()
-{}
-bool
-MyTest::RunTests (void)
-{
-  return m_ok;
-}
-
-// instantiate MyTest once
-static MyTest g_my_test = MyTest (true);
-
-#endif /* RUN_SELF_TESTS */
-
-int main (int argc, char *argv[])
-{
-  // run tests
-  TestManager::EnableVerbose ();
-  TestManager::RunTests ();
-  return 0;
-}
--- a/samples/wscript	Mon Sep 28 10:04:32 2009 -0700
+++ b/samples/wscript	Mon Sep 28 10:11:05 2009 -0700
@@ -22,9 +22,6 @@
     obj = bld.create_ns3_program('main-packet-tag', ['common', 'simulator'])
     obj.source = 'main-packet-tag.cc'
 
-    obj = bld.create_ns3_program('main-test')
-    obj.source = 'main-test.cc'
-
     if bld.env['ENABLE_THREADING'] and bld.env["ENABLE_REAL_TIME"]:
         obj = bld.create_ns3_program('main-test-sync')
         obj.source = 'main-test-sync.cc'
@@ -53,4 +50,3 @@
                                  ['core', 'simulator', 'mobility', 'wifi'])
     obj.source = 'main-ns2-mob.cc'
 
-
--- a/src/devices/wifi/supported-rates.cc	Mon Sep 28 10:04:32 2009 -0700
+++ b/src/devices/wifi/supported-rates.cc	Mon Sep 28 10:11:05 2009 -0700
@@ -136,7 +136,7 @@
         {
           os << "*";
         }
-      os << rate << "mbs";
+      os << rate / 1000000 << "mbs";
       if (i < rates.GetNRates () - 1)
         {
           os << " ";
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/ns3wifi/wifi-interference-test-suite.cc	Mon Sep 28 10:11:05 2009 -0700
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2009 University of Washington
+ *
+ * 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 <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+
+#include "ns3/log.h"
+#include "ns3/callback.h"
+#include "ns3/abort.h"
+#include "ns3/test.h"
+#include "ns3/pcap-file.h"
+#include "ns3/config.h"
+#include "ns3/string.h"
+#include "ns3/uinteger.h"
+#include "ns3/data-rate.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/yans-wifi-helper.h"
+#include "ns3/propagation-loss-model.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/yans-wifi-channel.h"
+#include "ns3/yans-wifi-phy.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/constant-position-mobility-model.h"
+#include "ns3/nqos-wifi-mac-helper.h"
+#include "ns3/simulator.h"
+
+NS_LOG_COMPONENT_DEFINE ("WifiInterferenceTestSuite");
+
+using namespace ns3;
+
+class WifiInterferenceTestCase : public TestCase
+{
+public:
+  WifiInterferenceTestCase ();
+  virtual ~WifiInterferenceTestCase ();
+
+private:
+  virtual bool DoRun (void);
+  void ReceivePacket (Ptr<Socket> socket);
+  static void GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval);
+  void PrintEndSync (std::string context, uint32_t dataRate, double snr, double per);
+  double WifiSimpleInterference (std::string phyMode, double Prss, double Irss, double delta, uint32_t PpacketSize, 
+    uint32_t IpacketSize, bool verbose, InternetStackHelper internet);
+  double m_PER;
+  double m_SNR;
+  uint32_t m_DataRate;
+};
+
+// Add some help text to this case to describe what it is intended to test
+WifiInterferenceTestCase::WifiInterferenceTestCase  ()
+  : TestCase ("Test interference calculation when interfering frame exactly overlaps intended frame")
+{
+}
+
+WifiInterferenceTestCase::~WifiInterferenceTestCase ()
+{
+}
+
+void 
+WifiInterferenceTestCase::ReceivePacket (Ptr<Socket> socket)
+{
+  Address addr;
+  socket->GetSockName (addr);
+  InetSocketAddress iaddr = InetSocketAddress::ConvertFrom (addr);
+  NS_LOG_UNCOND ("Received one packet!  Socket: " << iaddr.GetIpv4 () << " port: " << iaddr.GetPort ());
+}
+
+void 
+WifiInterferenceTestCase::GenerateTraffic (Ptr<Socket> socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval)
+{
+  if (pktCount > 0)
+    {
+      socket->Send (Create<Packet> (pktSize));
+      Simulator::Schedule (pktInterval, &WifiInterferenceTestCase::GenerateTraffic, socket, pktSize, pktCount-1, pktInterval);
+    }
+  else
+    {
+      socket->Close ();
+    }
+}
+
+void 
+WifiInterferenceTestCase::PrintEndSync (std::string context, uint32_t dataRate, double snr, double per)
+{
+  NS_LOG_UNCOND ("EndSync:  Received frame with dataRate=" << dataRate << ", SNR=" << snr << ", PER =" << per);
+  m_PER = per;
+  m_SNR = snr;
+  m_DataRate = dataRate;
+}
+
+double 
+WifiInterferenceTestCase::WifiSimpleInterference (std::string phyMode,double Prss, double Irss, double delta, uint32_t PpacketSize, uint32_t IpacketSize, bool verbose, InternetStackHelper internet)
+{
+  
+  uint32_t numPackets = 1;
+  double interval = 1.0; // seconds
+  double startTime = 10.0; // seconds
+  double distanceToRx = 100.0; // meters
+  
+  double offset = 91;  // This is a magic number used to set the 
+  // transmit power, based on other configuration
+  
+  m_PER = 0;
+  m_SNR = 0;
+  m_DataRate = 0;
+  
+  // Convert to time object
+  Time interPacketInterval = Seconds (interval);
+  
+  // disable fragmentation for frames below 2200 bytes
+  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
+  // turn off RTS/CTS for frames below 2200 bytes
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+  // Fix non-unicast data rate to be the same as that of unicast
+  Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", 
+                      StringValue (phyMode));
+  
+  NodeContainer c;
+  c.Create (3);
+  
+  // The below set of helpers will help us to put together the wifi NICs we want
+  WifiHelper wifi;
+  wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+  
+  YansWifiPhyHelper wifiPhy =  YansWifiPhyHelper::Default ();
+  // This is one parameter that matters when using FixedRssLossModel
+  // set it to zero; otherwise, gain will be added
+  wifiPhy.Set ("RxGain", DoubleValue (0) ); 
+  wifiPhy.Set ("CcaMode1Threshold", DoubleValue (0.0) );
+  
+  // ns-3 support RadioTap and Prism tracing extensions for 802.11b
+  wifiPhy.SetPcapFormat (YansWifiPhyHelper::PCAP_FORMAT_80211_RADIOTAP); 
+  
+  YansWifiChannelHelper wifiChannel ;
+  wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+  wifiChannel.AddPropagationLoss ("ns3::LogDistancePropagationLossModel");
+  wifiPhy.SetChannel (wifiChannel.Create ());
+  
+  // Add a non-QoS upper mac, and disable rate control
+  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
+                                "DataMode",StringValue(phyMode),
+                                "ControlMode",StringValue(phyMode));
+  // Set it to adhoc mode
+  wifiMac.SetType ("ns3::AdhocWifiMac");
+  NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, c.Get (0));
+  // This will disable these sending devices from detecting a signal 
+  // so that they do not backoff
+  wifiPhy.Set ("EnergyDetectionThreshold", DoubleValue (0.0) );
+  wifiPhy.Set ("TxGain", DoubleValue (offset + Prss) ); 
+  devices.Add (wifi.Install (wifiPhy, wifiMac, c.Get (1)));
+  wifiPhy.Set ("TxGain", DoubleValue (offset + Irss) ); 
+  devices.Add (wifi.Install (wifiPhy, wifiMac, c.Get (2)));
+  
+  // Note that with FixedRssLossModel, the positions below are not 
+  // used for received signal strength. 
+  MobilityHelper mobility;
+  Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator> ();
+  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
+  positionAlloc->Add (Vector (distanceToRx, 0.0, 0.0));
+  positionAlloc->Add (Vector (-1*distanceToRx, 0.0, 0.0));
+  mobility.SetPositionAllocator (positionAlloc);
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (c);
+
+ // InternetStackHelper internet;
+  internet.Install (c);
+ 
+  Ipv4AddressHelper ipv4;
+  NS_LOG_INFO ("Assign IP Addresses.");
+  ipv4.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer i = ipv4.Assign (devices);
+  
+  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+  Ptr<Socket> recvSink = Socket::CreateSocket (c.Get (0), tid);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address("10.1.1.1"), 80);
+  recvSink->Bind (local);
+  recvSink->SetRecvCallback (MakeCallback (&WifiInterferenceTestCase::ReceivePacket, this));
+  
+  Ptr<Socket> source = Socket::CreateSocket (c.Get (1), tid);
+  InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), 80);
+  source->Connect (remote);
+  
+  // Interferer will send to a different port; we will not see a
+  // "Received packet" message
+  Ptr<Socket> interferer = Socket::CreateSocket (c.Get (2), tid);
+  InetSocketAddress interferingAddr = InetSocketAddress (Ipv4Address ("255.255.255.255"), 49000);
+  interferer->Connect (interferingAddr);
+  
+  Config::Connect ("/NodeList/0/DeviceList/0/$ns3::WifiNetDevice/Phy/$ns3::YansWifiPhy/EndSync", MakeCallback (&WifiInterferenceTestCase::PrintEndSync, this)); 
+  // Tracing
+  wifiPhy.EnablePcap ("wifi-simple-interference", devices.Get (0));
+  
+  Simulator::Schedule (Seconds (startTime), &GenerateTraffic, 
+                       source, PpacketSize, numPackets, interPacketInterval);
+  
+  Simulator::Schedule (Seconds (startTime + delta/1000000.0), &GenerateTraffic, 
+                       interferer, IpacketSize, numPackets, interPacketInterval);
+  
+  Simulator::Run ();
+  Simulator::Destroy ();
+  
+  return m_PER;
+}
+
+bool
+WifiInterferenceTestCase::DoRun (void)
+{
+
+  std::string phyMode ("wifib-1mbs");
+  double Prss = -90;  // -dBm
+  double Irss = -90;  // -dBm
+  double delta = 0;  // microseconds
+  uint32_t PpacketSize = 1000; // bytes
+  uint32_t IpacketSize = 1000; // bytes
+  bool verbose = false;
+  double PER, PER1, PER2;
+  InternetStackHelper internet;
+  
+  // Compute the packet error rate (PER) when delta=0 microseconds.  This
+  // means that the interferer arrives at exactly the same time as the
+  // intended packet
+  PER = WifiSimpleInterference (phyMode,Prss,Irss,delta,PpacketSize,IpacketSize,verbose,internet);
+  
+  // Now rerun this test case and compute the PER when the delta time between
+  // arrival of the intended frame and interferer is 1 microsecond.
+  delta = 1;
+  PER1 = WifiSimpleInterference (phyMode,Prss,Irss,delta,PpacketSize,IpacketSize,verbose,internet);
+  
+  // Now rerun this test case and compute the PER when the delta time between
+  // arrival of the intended frame and interferer is 2 microseconds.
+  delta = 2;
+  PER2 = WifiSimpleInterference (phyMode,Prss,Irss,delta,PpacketSize,IpacketSize,verbose,internet);
+  
+  double PERDiff1 = PER - PER1;
+  
+  double PERDiff2 = PER1 - PER2;
+  
+  NS_TEST_ASSERT_MSG_EQ (PERDiff1, PERDiff2, 
+    "The PER difference due to 1 microsecond difference in arrival shouldn't depend on absolute arrival");
+  
+  return false;
+}
+
+class WifiInterferenceTestSuite : public TestSuite
+{
+public:
+  WifiInterferenceTestSuite ();
+};
+
+WifiInterferenceTestSuite::WifiInterferenceTestSuite ()
+  : TestSuite ("ns3-wifi-interference", UNIT)
+{
+  AddTestCase (new WifiInterferenceTestCase);
+}
+
+WifiInterferenceTestSuite wifiInterferenceTestSuite;
+
--- a/src/test/ns3wifi/wscript	Mon Sep 28 10:04:32 2009 -0700
+++ b/src/test/ns3wifi/wscript	Mon Sep 28 10:11:05 2009 -0700
@@ -7,6 +7,7 @@
     ns3wifi = bld.create_ns3_module('ns3wifi')
     ns3wifi.source = [
         'propagation-loss-models-test-suite.cc',
+        'wifi-interference-test-suite.cc',
         ]
     headers = bld.new_task_gen('ns3header')
     headers.module = 'ns3wifi'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/sample-test-suite.cc	Mon Sep 28 10:11:05 2009 -0700
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+// An essential include is test.h
+#include "ns3/test.h"
+
+// Do not put your test classes in namespace ns3.  You may find it useful
+// to use the using directive to access the ns3 namespace directly
+using namespace ns3;
+
+// This is an example TestCase.  
+class SampleTestCase1 : public TestCase
+{
+public:
+  SampleTestCase1 ();
+  virtual ~SampleTestCase1 ();
+
+private:
+  virtual bool DoRun (void);
+};
+
+// Add some help text to this case to describe what it is intended to test
+SampleTestCase1::SampleTestCase1 ()
+  : TestCase ("Sample test case (does nothing)")
+{
+}
+
+// This destructor does nothing but we include it as a reminder that
+// the test case should clean up after itself
+SampleTestCase1::~SampleTestCase1 ()
+{
+}
+
+//
+// This method is the pure virtual method from class TestCase that every
+// TestCase must implement
+//
+bool
+SampleTestCase1::DoRun (void)
+{
+  // A wide variety of test macros are available in src/core/test.h
+  NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
+  // Use this one for floating point comparisons
+  NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
+
+  // Return false if an error has _not_ occurred
+  return false;
+}
+
+// The TestSuite class names the TestSuite, identifies what type of TestSuite,
+// and enables the TestCases to be run.  Typically, only the constructor for
+// this class must be defined
+//
+class SampleTestSuite : public TestSuite
+{
+public:
+  SampleTestSuite ();
+};
+
+SampleTestSuite::SampleTestSuite ()
+  : TestSuite ("sample", BVT)
+{
+  AddTestCase (new SampleTestCase1);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+SampleTestSuite sampleTestSuite;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/wscript	Mon Sep 28 10:11:05 2009 -0700
@@ -0,0 +1,12 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    test = bld.create_ns3_module('test', ['core'])
+    test.source = [
+        'sample-test-suite.cc',
+        ]
+
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'test'
+    headers.source = [
+        ]
--- a/src/wscript	Mon Sep 28 10:04:32 2009 -0700
+++ b/src/wscript	Mon Sep 28 10:11:05 2009 -0700
@@ -42,6 +42,7 @@
     'devices/mesh/flame',
     'applications/ping6',
     'applications/radvd',
+    'test',
     'test/ns3tcp',
     'test/ns3wifi',
     'contrib/flow-monitor',