src/wifi/test/wifi-test.cc
changeset 9176 41ab1e874804
parent 7385 10beb0e53130
child 9266 d26408b17360
--- a/src/wifi/test/wifi-test.cc	Fri Dec 07 10:12:40 2012 -0800
+++ b/src/wifi/test/wifi-test.cc	Fri Dec 07 14:36:01 2012 -0500
@@ -37,6 +37,7 @@
 #include "ns3/dca-txop.h"
 #include "ns3/mac-rx-middle.h"
 #include "ns3/pointer.h"
+#include "ns3/rng-seed-manager.h"
 
 namespace ns3 {
 
@@ -285,6 +286,148 @@
 }
 
 //-----------------------------------------------------------------------------
+/**
+ * Make sure that when multiple broadcast packets are queued on the same
+ * device in a short succession no virtual collision occurs 
+ *
+ * The observed behavior is that the first frame will be sent immediately,
+ * and the frames are spaced by (backoff + SIFS + AIFS) time intervals
+ * (where backoff is a random number of slot sizes up to maximum CW)
+ * 
+ * The following test case should _not_ generate virtual collision for the second frame.
+ * The seed and run numbers were pick such that the second frame gets backoff = 0.
+ *
+ *                      frame 1, frame 2
+ *                      arrive                SIFS + AIFS
+ *                      V                    <-----------> 
+ * time  |--------------|-------------------|-------------|----------->
+ *       0              1s                  1.001408s     1.001442s
+ *                      ^                   ^             ^
+ *                      start TX            finish TX     start TX
+ *                      frame 1             frame 1       frame 2
+ *                      ^
+ *                      frame 2
+ *                      backoff = 0
+ *
+ * The buggy behavior was that frame 2 experiences a virtual collision and re-selects the
+ * backoff again. As a result, the _actual_ backoff experience by frame 2 is less likely to be 0
+ * since that would require two successions of 0 backoff (one that generates the virtual collision and
+ * one after the virtual collision).
+ */
+
+class Bug555TestCase : public TestCase
+{
+public:
+
+  Bug555TestCase ();
+
+  virtual void DoRun (void);
+
+private:
+
+  void SendOnePacket (Ptr<WifiNetDevice> dev);
+
+  ObjectFactory m_manager;
+  ObjectFactory m_mac; 
+  ObjectFactory m_propDelay;
+
+  Time m_firstTransmissionTime;
+  Time m_secondTransmissionTime;
+  unsigned int m_numSentPackets;
+
+  void NotifyPhyTxBegin (Ptr<const Packet> p);
+};
+
+Bug555TestCase::Bug555TestCase ()
+  : TestCase ("Test case for Bug 555")
+{
+}
+
+void 
+Bug555TestCase::NotifyPhyTxBegin (Ptr<const Packet> p)
+{
+  if (m_numSentPackets == 0)
+    {
+      NS_ASSERT_MSG (Simulator::Now() == Time (Seconds (1)), "Packet 0 not transmitted at 1 second");
+      m_numSentPackets++;
+      m_firstTransmissionTime = Simulator::Now ();
+    }
+  else if (m_numSentPackets == 1)
+    {
+      m_secondTransmissionTime = Simulator::Now ();
+    }
+}
+
+void
+Bug555TestCase::SendOnePacket (Ptr<WifiNetDevice> dev)
+{
+  Ptr<Packet> p = Create<Packet> (1000);
+  dev->Send (p, dev->GetBroadcast (), 1);
+}
+
+void
+Bug555TestCase::DoRun (void)
+{
+  m_mac.SetTypeId ("ns3::AdhocWifiMac");
+  m_propDelay.SetTypeId ("ns3::ConstantSpeedPropagationDelayModel");
+  m_manager.SetTypeId ("ns3::ConstantRateWifiManager");
+
+  //The simulation with the following seed and run numbers expe
+  RngSeedManager::SetSeed (1);
+  RngSeedManager::SetRun (17);
+
+  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
+  Ptr<PropagationDelayModel> propDelay = m_propDelay.Create<PropagationDelayModel> ();
+  Ptr<PropagationLossModel> propLoss = CreateObject<RandomPropagationLossModel> ();
+  channel->SetPropagationDelayModel (propDelay);
+  channel->SetPropagationLossModel (propLoss);
+
+  Ptr<Node> txNode = CreateObject<Node> ();
+  Ptr<WifiNetDevice> txDev = CreateObject<WifiNetDevice> ();
+  Ptr<WifiMac> txMac = m_mac.Create<WifiMac> ();
+  txMac->ConfigureStandard (WIFI_PHY_STANDARD_80211a);
+
+  Ptr<ConstantPositionMobilityModel> txMobility = CreateObject<ConstantPositionMobilityModel> ();
+  Ptr<YansWifiPhy> txPhy = CreateObject<YansWifiPhy> ();
+  Ptr<ErrorRateModel> txError = CreateObject<YansErrorRateModel> ();
+  txPhy->SetErrorRateModel (txError);
+  txPhy->SetChannel (channel);
+  txPhy->SetDevice (txDev);
+  txPhy->SetMobility (txNode);
+  txPhy->ConfigureStandard (WIFI_PHY_STANDARD_80211a);
+
+  txPhy->TraceConnectWithoutContext ("PhyTxBegin", MakeCallback (&Bug555TestCase::NotifyPhyTxBegin, this));
+
+  txMobility->SetPosition (Vector (0.0, 0.0, 0.0));
+  txNode->AggregateObject (txMobility);
+  txMac->SetAddress (Mac48Address::Allocate ());
+  txDev->SetMac (txMac);
+  txDev->SetPhy (txPhy);
+  txDev->SetRemoteStationManager (m_manager.Create<WifiRemoteStationManager> ());
+  txNode->AddDevice (txDev);
+
+  m_firstTransmissionTime = Seconds (0.0);
+  m_secondTransmissionTime = Seconds (0.0);
+  m_numSentPackets = 0;
+  
+  Simulator::Schedule (Seconds (1.0), &Bug555TestCase::SendOnePacket, this, txDev);
+  Simulator::Schedule (Seconds (1.0), &Bug555TestCase::SendOnePacket, this, txDev);
+
+  Simulator::Stop (Seconds (2.0));
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // First packet has 1408 us of transmit time.   Slot time is 9 us.  
+  // Backoff is 0 slots.  SIFS is 16 us.  AIFS is 2 slots = 18 us.
+  // Should send next packet at 1408 us + (0 * 9 us) + 16 us + 18 us
+  // 1442 us after the first one.
+  uint32_t expectedWait1 = 1408 + (0 * 9) + 16 + 18;
+  Time expectedSecondTransmissionTime = MicroSeconds (expectedWait1) + Seconds (1.0);
+
+  NS_TEST_ASSERT_MSG_EQ (m_secondTransmissionTime, expectedSecondTransmissionTime, "The second transmission time not correct!");
+}
+
+//-----------------------------------------------------------------------------
 
 class WifiTestSuite : public TestSuite
 {
@@ -298,6 +441,7 @@
   AddTestCase (new WifiTest);
   AddTestCase (new QosUtilsIsOldPacketTest);
   AddTestCase (new InterferenceHelperSequenceTest); // Bug 991
+  AddTestCase (new Bug555TestCase); // Bug 555
 }
 
 static WifiTestSuite g_wifiTestSuite;