Add BurstErrorModel class

This commit is contained in:
Anh Nguyen
2013-04-19 12:58:25 -07:00
parent 0dc496c3bf
commit 14506d5d6e
5 changed files with 369 additions and 6 deletions

View File

@@ -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<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

View File

@@ -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 <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.

View File

@@ -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 @@ 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<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 @@ 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

View File

@@ -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 @@ 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<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 @@ ReceiveListErrorModel::DoReset (void)
} // namespace ns3

View File

@@ -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 @@ 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<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
*