From 14506d5d6eb72a4ff56469dda5df753e4e714a56 Mon Sep 17 00:00:00 2001 From: Anh Nguyen Date: Fri, 19 Apr 2013 12:58:25 -0700 Subject: [PATCH] Add BurstErrorModel class --- examples/error-model/simple-error-model.cc | 15 ++- src/network/doc/error-model.rst | 17 +++ src/network/test/error-model-test-suite.cc | 105 ++++++++++++++++ src/network/utils/error-model.cc | 138 +++++++++++++++++++++ src/network/utils/error-model.h | 100 ++++++++++++++- 5 files changed, 369 insertions(+), 6 deletions(-) diff --git a/examples/error-model/simple-error-model.cc b/examples/error-model/simple-error-model.cc index ddcc7cc21..37782f2fe 100644 --- a/examples/error-model/simple-error-model.cc +++ b/examples/error-model/simple-error-model.cc @@ -57,16 +57,21 @@ main (int argc, char *argv[]) // 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 @@ main (int argc, char *argv[]) // Error model // // Create an ErrorModel based on the implementation (constructor) - // specified by the default classId - Ptr em = CreateObject (); - em->SetAttribute ("ErrorRate", DoubleValue (0.001)); + // specified by the default TypeId + + ObjectFactory factory; + factory.SetTypeId (errorModelType); + Ptr em = factory.Create (); d3d2.Get (0)->SetAttribute ("ReceiveErrorModel", PointerValue (em)); // Now, let's use the ListErrorModel and explicitly force a loss diff --git a/src/network/doc/error-model.rst b/src/network/doc/error-model.rst index b2d3e1d61..9ce7e9c6f 100644 --- a/src/network/doc/error-model.rst +++ b/src/network/doc/error-model.rst @@ -134,3 +134,20 @@ The ``error-model`` unit test suite provides a single test case of 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 , 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. diff --git a/src/network/test/error-model-test-suite.cc b/src/network/test/error-model-test-suite.cc index 2d2af2324..e2b50cf3d 100644 --- a/src/network/test/error-model-test-suite.cc +++ b/src/network/test/error-model-test-suite.cc @@ -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 + * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets + * James P.G. Sterbenz , director + */ #include "ns3/test.h" #include "ns3/simple-net-device.h" @@ -117,6 +142,85 @@ ErrorModelSimple::DoRun (void) 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 nd, Ptr p, uint16_t protocol, const Address& addr); + void DropEvent (Ptr 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 nd, Ptr p, uint16_t protocol, const Address& addr) +{ + m_count++; + return true; +} + +void +BurstErrorModelSimple::DropEvent (Ptr p) +{ + m_drops++; +} + +void +BurstErrorModelSimple::DoRun (void) +{ + // Set some arbitrary deterministic values + RngSeedManager::SetSeed (5); + RngSeedManager::SetRun (8); + + Ptr a = CreateObject (); + Ptr b = CreateObject (); + + Ptr input = CreateObject (); + Ptr output = CreateObject (); + Ptr channel = CreateObject (); + BuildSimpleTopology (a, b, input, output, channel); + + output->SetReceiveCallback (MakeCallback (&BurstErrorModelSimple::Receive, this)); + Ptr uv = CreateObject (); + // Set this variable to a specific stream + uv->SetStream (50); + + Ptr em = CreateObject (); + 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 @@ ErrorModelTestSuite::ErrorModelTestSuite () : TestSuite ("error-model", UNIT) { AddTestCase (new ErrorModelSimple, TestCase::QUICK); + AddTestCase (new BurstErrorModelSimple, TestCase::QUICK); } // Do not forget to allocate an instance of this TestSuite diff --git a/src/network/utils/error-model.cc b/src/network/utils/error-model.cc index 914786044..f99303ba9 100644 --- a/src/network/utils/error-model.cc +++ b/src/network/utils/error-model.cc @@ -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 + * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets + * James P.G. Sterbenz , director + */ + #include #include "error-model.h" @@ -271,6 +279,135 @@ RateErrorModel::DoReset (void) /* 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 () + .AddConstructor () + .AddAttribute ("ErrorRate", "The burst error event.", + DoubleValue (0.0), + MakeDoubleAccessor (&BurstErrorModel::m_burstRate), + MakeDoubleChecker ()) + .AddAttribute ("BurstStart", "The decision variable attached to this error model.", + StringValue ("ns3::UniformRandomVariable[Min=0.0|Max=1.0]"), + MakePointerAccessor (&BurstErrorModel::m_burstStart), + MakePointerChecker ()) + .AddAttribute ("BurstSize", "The number of packets being corrupted at one drop.", + StringValue ("ns3::UniformRandomVariable[Min=1|Max=4]"), + MakePointerAccessor (&BurstErrorModel::m_burstSize), + MakePointerChecker ()) + ; + 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 ranVar) +{ + NS_LOG_FUNCTION (this << ranVar); + m_burstStart = ranVar; +} + +void +BurstErrorModel::SetRandomBurstSize(Ptr 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 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 @@ ReceiveListErrorModel::DoReset (void) } // namespace ns3 + diff --git a/src/network/utils/error-model.h b/src/network/utils/error-model.h index a514d7ba4..cad004699 100644 --- a/src/network/utils/error-model.h +++ b/src/network/utils/error-model.h @@ -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 + * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets + * James P.G. Sterbenz , director + */ + #ifndef ERROR_MODEL_H #define ERROR_MODEL_H @@ -101,8 +109,8 @@ class Packet; * } * \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 @@ private: Ptr 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); + + /** + * \param burstSize A random variable distribution to generate random burst size + */ + void SetRandomBurstSize (Ptr); + + /** + * 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 p); + virtual void DoReset (void); + + double m_burstRate; //the burst error event + + Ptr m_burstStart; //the error decision variable + + Ptr 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 *