Add BurstErrorModel class
authorAnh Nguyen <annguyen@ittc.ku.edu>
Fri, 19 Apr 2013 12:58:25 -0700
changeset 9702 552d0701ee4e
parent 9701 48ee4490478f
child 9703 681f35b212ff
Add BurstErrorModel class
examples/error-model/simple-error-model.cc
src/network/doc/error-model.rst
src/network/test/error-model-test-suite.cc
src/network/utils/error-model.cc
src/network/utils/error-model.h
--- a/examples/error-model/simple-error-model.cc	Fri Apr 19 14:52:17 2013 -0400
+++ b/examples/error-model/simple-error-model.cc	Fri Apr 19 12:58:25 2013 -0700
@@ -57,16 +57,21 @@
 
 
   // Set a few attributes
-  Config::SetDefault ("ns3::RateErrorModel::ErrorRate", DoubleValue (0.01));
+  Config::SetDefault ("ns3::RateErrorModel::ErrorRate", DoubleValue (0.001));
   Config::SetDefault ("ns3::RateErrorModel::ErrorUnit", StringValue ("ERROR_UNIT_PACKET"));
 
+  Config::SetDefault ("ns3::BurstErrorModel::ErrorRate", DoubleValue (0.01));
+  Config::SetDefault ("ns3::BurstErrorModel::BurstSize", StringValue ("ns3::UniformRandomVariable[Min=1|Max=3]"));
+
   Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
   Config::SetDefault ("ns3::OnOffApplication::DataRate", DataRateValue (DataRate ("448kb/s")));
 
+  std::string errorModelType = "ns3::RateErrorModel";
 
   // Allow the user to override any of the defaults and the above
   // Bind()s at run-time, via command-line arguments
   CommandLine cmd;
+  cmd.AddValue("errorModelType", "TypeId of the error model to use", errorModelType);
   cmd.Parse (argc, argv);
 
   // Here, we will explicitly create four nodes.  In more sophisticated
@@ -146,9 +151,11 @@
   // Error model
   //
   // Create an ErrorModel based on the implementation (constructor)
-  // specified by the default classId
-  Ptr<RateErrorModel> em = CreateObject<RateErrorModel> ();
-  em->SetAttribute ("ErrorRate", DoubleValue (0.001));
+  // specified by the default TypeId
+ 
+  ObjectFactory factory;
+  factory.SetTypeId (errorModelType);
+  Ptr<ErrorModel> em = factory.Create<ErrorModel> ();
   d3d2.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
 
   // Now, let's use the ListErrorModel and explicitly force a loss
--- a/src/network/doc/error-model.rst	Fri Apr 19 14:52:17 2013 -0400
+++ b/src/network/doc/error-model.rst	Fri Apr 19 12:58:25 2013 -0700
@@ -134,3 +134,20 @@
 of a particular combination of ErrorRate and ErrorUnit for the 
 ``RateErrorModel`` applied to a ``SimpleNetDevice``. 
 
+Acknowledgements
+****************
+
+The basic ErrorModel, RateErrorModel, and ListErrorModel classes were ported
+from |ns2| to |ns3| in 2007.  The ReceiveListErrorModel was added at that
+time.
+
+The burst error model is due to Truc Anh N. Nguyen at the University of
+Kansas (James P.G. Sterbenz <jpgs@ittc.ku.edu>, director, ResiliNets 
+Research Group (http://wiki.ittc.ku.edu/resilinets), Information and 
+Telecommunication Technology Center (ITTC) and Department of Electrical 
+Engineering and Computer Science, The University of Kansas Lawrence, KS USA).
+Work supported in part by NSF FIND (Future Internet Design) Program
+under grant CNS-0626918 (Postmodern Internet Architecture),
+NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and 
+Experimentation on GENI), US Department of Defense (DoD), and ITTC at 
+The University of Kansas.
--- a/src/network/test/error-model-test-suite.cc	Fri Apr 19 14:52:17 2013 -0400
+++ b/src/network/test/error-model-test-suite.cc	Fri Apr 19 12:58:25 2013 -0700
@@ -1,4 +1,29 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * Copyright (c) 2013 ResiliNets, ITTC, University of Kansas 
+ *
+ * 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
+ *
+ */
+
+/* BurstErrorModel additions
+ *
+ * Author: Truc Anh N. Nguyen   <annguyen@ittc.ku.edu>
+ *         ResiliNets Research Group   http://wiki.ittc.ku.edu/resilinets
+ *         James P.G. Sterbenz <jpgs@ittc.ku.edu>, director 
+ */
 
 #include "ns3/test.h"
 #include "ns3/simple-net-device.h"
@@ -117,6 +142,85 @@
   NS_TEST_ASSERT_MSG_EQ (m_drops, 9, "Wrong number of drops.");
 }
 
+class BurstErrorModelSimple : public TestCase
+{
+public:
+  BurstErrorModelSimple ();
+  virtual ~BurstErrorModelSimple ();
+
+private:
+  virtual void DoRun (void);
+  bool Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr);
+  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
+BurstErrorModelSimple::BurstErrorModelSimple ()
+  : TestCase ("ErrorModel and PhyRxDrop trace for SimpleNetDevice"), m_count (0), m_drops (0)
+{
+}
+
+BurstErrorModelSimple::~BurstErrorModelSimple ()
+{
+}
+
+bool
+BurstErrorModelSimple::Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr)
+{
+  m_count++;
+  return true;
+}
+
+void
+BurstErrorModelSimple::DropEvent (Ptr<const Packet> p)
+{
+  m_drops++;
+}
+
+void
+BurstErrorModelSimple::DoRun (void)
+{
+  // Set some arbitrary deterministic values
+  RngSeedManager::SetSeed (5);
+  RngSeedManager::SetRun (8);
+
+  Ptr<Node> a = CreateObject<Node> ();
+  Ptr<Node> b = CreateObject<Node> ();
+
+  Ptr<SimpleNetDevice> input = CreateObject<SimpleNetDevice> ();
+  Ptr<SimpleNetDevice> output = CreateObject<SimpleNetDevice> ();
+  Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
+  BuildSimpleTopology (a, b, input, output, channel);
+
+  output->SetReceiveCallback (MakeCallback (&BurstErrorModelSimple::Receive, this));
+  Ptr<UniformRandomVariable> uv = CreateObject<UniformRandomVariable> ();
+  // Set this variable to a specific stream
+  uv->SetStream (50);
+
+  Ptr<BurstErrorModel> em = CreateObject<BurstErrorModel> ();
+  em->SetRandomVariable (uv);
+  em->SetAttribute ("ErrorRate", DoubleValue (0.01));
+
+  // The below hooks will cause drops and receptions to be counted
+  output->SetAttribute ("ReceiveErrorModel", PointerValue (em));
+  output->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&BurstErrorModelSimple::DropEvent, this));
+
+  // Send 10000 packets
+  Simulator::Schedule (Seconds (0), &SendPacket, 10000, input, output->GetAddress ());
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  // With the burst error rate to be 0.01 and the burst size to be from 1 to 4,
+  // we expect about 2.5 packets being dropped every 1000 packets.
+  // That means for 10000 packets, we expect a total of about 250 packet drops.
+  // For this specific RNG seed, we see 9772 receptions and 228 drops.
+  NS_TEST_ASSERT_MSG_EQ (m_count, 9772, "Wrong number of receptions.");
+  NS_TEST_ASSERT_MSG_EQ (m_drops, 228 , "Wrong number of drops.");
+}
+
 // This is the start of an error model test suite.  For starters, this is
 // just testing that the SimpleNetDevice is working but this can be
 // extended to many more test cases in the future
@@ -130,6 +234,7 @@
   : TestSuite ("error-model", UNIT)
 {
   AddTestCase (new ErrorModelSimple, TestCase::QUICK);
+  AddTestCase (new BurstErrorModelSimple, TestCase::QUICK);
 }
 
 // Do not forget to allocate an instance of this TestSuite
--- a/src/network/utils/error-model.cc	Fri Apr 19 14:52:17 2013 -0400
+++ b/src/network/utils/error-model.cc	Fri Apr 19 12:58:25 2013 -0700
@@ -1,6 +1,7 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2007 University of Washington
+ * Copyright (c) 2013 ResiliNets, ITTC, University of Kansas 
  *
  * 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
@@ -52,6 +53,13 @@
  * This code has been ported from ns-2 (queue/errmodel.{cc,h}
  */
 
+/* BurstErrorModel additions
+ *
+ * Author: Truc Anh N. Nguyen   <annguyen@ittc.ku.edu>
+ *         ResiliNets Research Group   http://wiki.ittc.ku.edu/resilinets
+ *         James P.G. Sterbenz <jpgs@ittc.ku.edu>, director 
+ */
+
 #include <cmath>
 
 #include "error-model.h"
@@ -271,6 +279,135 @@
   /* re-initialize any state; no-op for now */ 
 }
 
+
+//
+// BurstErrorModel
+//
+
+NS_OBJECT_ENSURE_REGISTERED (BurstErrorModel);
+
+TypeId BurstErrorModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::BurstErrorModel")
+    .SetParent<ErrorModel> ()
+    .AddConstructor<BurstErrorModel> ()
+    .AddAttribute ("ErrorRate", "The burst error event.",
+                   DoubleValue (0.0),
+                   MakeDoubleAccessor (&BurstErrorModel::m_burstRate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("BurstStart", "The decision variable attached to this error model.",
+                   StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1.0]"),
+                   MakePointerAccessor (&BurstErrorModel::m_burstStart),
+                   MakePointerChecker<RandomVariableStream> ())
+    .AddAttribute ("BurstSize", "The number of packets being corrupted at one drop.",
+                   StringValue ("ns3::UniformRandomVariable[Min=1|Max=4]"),
+                   MakePointerAccessor (&BurstErrorModel::m_burstSize),
+                   MakePointerChecker<RandomVariableStream> ())
+  ;
+  return tid;
+}
+
+
+BurstErrorModel::BurstErrorModel () : m_counter (0), m_currentBurstSz (0)
+{
+
+}
+
+BurstErrorModel::~BurstErrorModel ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+double
+BurstErrorModel::GetBurstRate (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_burstRate;
+}
+
+void
+BurstErrorModel::SetBurstRate (double rate)
+{
+  NS_LOG_FUNCTION (this << rate);
+  m_burstRate = rate;
+}
+
+void
+BurstErrorModel::SetRandomVariable (Ptr<RandomVariableStream> ranVar)
+{
+  NS_LOG_FUNCTION (this << ranVar);
+  m_burstStart = ranVar;
+}
+
+void
+BurstErrorModel::SetRandomBurstSize(Ptr<RandomVariableStream> burstSz)
+{
+  NS_LOG_FUNCTION (this << burstSz);
+  m_burstSize = burstSz;
+}
+
+int64_t
+BurstErrorModel::AssignStreams (int64_t stream)
+{
+  NS_LOG_FUNCTION (this << stream);
+  m_burstStart->SetStream (stream);
+  m_burstSize->SetStream(stream);
+  return 1;
+}
+
+bool
+BurstErrorModel::DoCorrupt (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this);
+  if (!IsEnabled ())
+    {
+      return false;
+    }
+  double ranVar = m_burstStart ->GetValue();
+
+  if (ranVar < m_burstRate)
+    {
+      // get a new burst size for the new error event
+      m_currentBurstSz = m_burstSize->GetInteger();     
+      NS_LOG_DEBUG ("new burst size selected: " << m_currentBurstSz);
+      if (m_currentBurstSz == 0)                        
+        {
+          NS_LOG_WARN ("Burst size == 0; shouldn't happen");
+          return false;
+        }
+      m_counter = 1;  // start counting dropped packets
+      return true;    // drop this packet
+    }
+  else
+    {
+      // not a burst error event
+      if (m_counter < m_currentBurstSz)
+        {
+         // check to see if all the packets (determined by the last 
+         // generated m_currentBurstSz) have been dropped. 
+         // If not, drop 1 more packet
+          m_counter++;                                 
+          return true;
+        }
+      else
+        {
+          // all packets in the last error event have been dropped
+          // and there is no new error event, so do not drop the packet
+          return false;  // no error event
+        }
+    }
+}
+
+void
+BurstErrorModel::DoReset (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_counter = 0;
+  m_currentBurstSz = 0;
+
+}
+
+
 //
 // ListErrorModel
 //
@@ -410,3 +547,4 @@
 
 
 } // namespace ns3
+
--- a/src/network/utils/error-model.h	Fri Apr 19 14:52:17 2013 -0400
+++ b/src/network/utils/error-model.h	Fri Apr 19 12:58:25 2013 -0700
@@ -1,6 +1,7 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2007 University of Washington
+ * Copyright (c) 2013 ResiliNets, ITTC, University of Kansas 
  *
  * 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
@@ -52,6 +53,13 @@
  * This code has been ported from ns-2 (queue/errmodel.{cc,h}
  */
 
+/* BurstErrorModel additions
+ *
+ * Author: Truc Anh N. Nguyen   <annguyen@ittc.ku.edu>
+ *         ResiliNets Research Group   http://wiki.ittc.ku.edu/resilinets
+ *         James P.G. Sterbenz <jpgs@ittc.ku.edu>, director 
+ */
+
 #ifndef ERROR_MODEL_H
 #define ERROR_MODEL_H
 
@@ -101,8 +109,8 @@
  *   }
  * \endcode
  *
- * Two practical error models, a ListErrorModel and a RateErrorModel,
- * are currently implemented. 
+ * Four practical error models, a RateErrorModel, a BurstErrorModel, 
+ * a ListErrorModel, and a ReceiveListErrorModel, are currently implemented. 
  */
 class ErrorModel : public Object
 {
@@ -223,6 +231,94 @@
   Ptr<RandomVariableStream> m_ranvar;
 };
 
+
+/**
+ * \brief Determine which bursts of packets are errored corresponding to 
+ * an underlying distribution, burst rate, and burst size.
+ *
+ * This object is used to flag packets as being lost/errored or not.
+ * The two parameters that govern the behavior are the burst rate (or
+ * equivalently, the mean duration/spacing between between error events), 
+ * and the burst size (or equivalently, the number of packets being flagged 
+ * as errored at each error event).
+ *
+ * Users can optionally provide RandomVariableStream objects;
+ * the default for the decision variable is to use a Uniform(0,1) distribution;
+ * the default for the burst size (number of packets) is to use a 
+ * discrete Uniform[1,4] distribution.
+ *
+ * For every packet, the model generates a random number based on the 
+ * decision variable, and compares it with the burst error rate to 
+ * determine if a burst error event should occur.
+ * If a new error event occurs, the model to will generate a new burst size 
+ * to determine how many packets should be dropped in this particular burst
+ * error event in addition to the current packet.
+ *
+ * When a second packet arrives, the model again determines if a new error 
+ * event should occur based on a newly generated decision variable and 
+ * the burst error rate. If a new error event is determined to occur, 
+ * the model will restart with a new burst size. Otherwise, the model will
+ * resume the last error event and drop the packet provided that the 
+ * total number of packets that has been dropped does not exceed the 
+ * burst size.
+ *
+ * IsCorrupt() will not modify the packet data buffer
+ */
+class BurstErrorModel : public ErrorModel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  BurstErrorModel ();
+  virtual ~BurstErrorModel ();
+
+  /**
+   * \returns the error rate being applied by the model
+   */
+  double GetBurstRate (void) const;
+  /**
+   * \param burstRate the error rate to be used by the model
+   */
+  void SetBurstRate (double rate);
+
+  /**
+   * \param ranVariable A random variable distribution to generate random variates
+   */
+  void SetRandomVariable (Ptr<RandomVariableStream>);
+
+  /**
+   * \param burstSize A random variable distribution to generate random burst size
+   */
+  void SetRandomBurstSize (Ptr<RandomVariableStream>);
+
+  /**
+    * Assign a fixed random variable stream number to the random variables
+    * used by this model.  Return the number of streams (possibly zero) that
+    * have been assigned.
+    *
+    * \param stream first stream index to use
+    * \return the number of stream indices assigned by this model
+    */
+  int64_t AssignStreams (int64_t stream);
+
+private:
+  virtual bool DoCorrupt (Ptr<Packet> p);
+  virtual void DoReset (void);
+
+  double m_burstRate;                         //the burst error event
+
+  Ptr<RandomVariableStream> m_burstStart;     //the error decision variable
+
+  Ptr<RandomVariableStream> m_burstSize;      //the number of packets being flagged as errored
+
+  uint32_t m_counter;                         //keep track of the number of packets being errored
+                                              //until it reaches m_burstSize
+
+  uint32_t m_currentBurstSz;                  //the current burst size
+
+};
+
+
 /**
  * \brief Provide a list of Packet uids to corrupt
  *