Add src/common/error-model implementation and example script, and add to NetDevices
This commit is contained in:
240
examples/simple-error-model.cc
Normal file
240
examples/simple-error-model.cc
Normal file
@@ -0,0 +1,240 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* ns-2 simple.tcl script (ported from ns-2)
|
||||
* Originally authored by Steve McCanne, 12/19/1996
|
||||
*/
|
||||
|
||||
// Port of ns-2/tcl/ex/simple.tcl to ns-3
|
||||
//
|
||||
// Network topology
|
||||
//
|
||||
// n0
|
||||
// \ 5 Mb/s, 2ms
|
||||
// \ 1.5Mb/s, 10ms
|
||||
// n2 -------------------------n3
|
||||
// /
|
||||
// / 5 Mb/s, 2ms
|
||||
// n1
|
||||
//
|
||||
// - all links are point-to-point links with indicated one-way BW/delay
|
||||
// - CBR/UDP flows from n0 to n3, and from n3 to n1
|
||||
// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
|
||||
// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
|
||||
// (i.e., DataRate of 448,000 bps)
|
||||
// - DropTail queues
|
||||
// - Tracing of queues and packet receptions to file
|
||||
// "simple-error-model.tr"
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/ptr.h"
|
||||
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/nstime.h"
|
||||
#include "ns3/data-rate.h"
|
||||
|
||||
#include "ns3/ascii-trace.h"
|
||||
#include "ns3/pcap-trace.h"
|
||||
#include "ns3/internet-node.h"
|
||||
#include "ns3/default-value.h"
|
||||
#include "ns3/component-manager.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/point-to-point-channel.h"
|
||||
#include "ns3/point-to-point-net-device.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/ipv4-route.h"
|
||||
#include "ns3/point-to-point-topology.h"
|
||||
#include "ns3/onoff-application.h"
|
||||
#include "ns3/packet-sink.h"
|
||||
#include "ns3/error-model.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("SimpleErrorModelExample");
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
// Users may find it convenient to turn on explicit debugging
|
||||
// for selected modules; the below lines suggest how to do this
|
||||
#if 0
|
||||
LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
|
||||
#endif
|
||||
|
||||
// Set up some default values for the simulation. Use the Bind()
|
||||
// technique to tell the system what subclass of ErrorModel to use
|
||||
DefaultValue::Bind ("ErrorModel", "RateErrorModel");
|
||||
// Set a few parameters
|
||||
DefaultValue::Bind ("RateErrorModelErrorRate", "0.01");
|
||||
DefaultValue::Bind ("RateErrorModelErrorUnit", "EU_PKT");
|
||||
|
||||
DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
|
||||
DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
|
||||
|
||||
|
||||
// Allow the user to override any of the defaults and the above
|
||||
// Bind()s at run-time, via command-line arguments
|
||||
CommandLine::Parse (argc, argv);
|
||||
|
||||
// Here, we will explicitly create four nodes. In more sophisticated
|
||||
// topologies, we could configure a node factory.
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> n0 = Create<InternetNode> ();
|
||||
Ptr<Node> n1 = Create<InternetNode> ();
|
||||
Ptr<Node> n2 = Create<InternetNode> ();
|
||||
Ptr<Node> n3 = Create<InternetNode> ();
|
||||
|
||||
// We create the channels first without any IP addressing information
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
Ptr<PointToPointChannel> channel0 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n0, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel1 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n1, n2, DataRate(5000000), MilliSeconds(2));
|
||||
|
||||
Ptr<PointToPointChannel> channel2 =
|
||||
PointToPointTopology::AddPointToPointLink (
|
||||
n2, n3, DataRate(1500000), MilliSeconds(10));
|
||||
|
||||
// Later, we add IP addresses.
|
||||
NS_LOG_INFO ("Assign IP Addresses.");
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel0, n0, Ipv4Address("10.1.1.1"),
|
||||
n2, Ipv4Address("10.1.1.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel1, n1, Ipv4Address("10.1.2.1"),
|
||||
n2, Ipv4Address("10.1.2.2"));
|
||||
|
||||
PointToPointTopology::AddIpv4Addresses (
|
||||
channel2, n2, Ipv4Address("10.1.3.1"),
|
||||
n3, Ipv4Address("10.1.3.2"));
|
||||
|
||||
// Finally, we add static routes. These three steps (Channel and
|
||||
// NetDevice creation, IP Address assignment, and routing) are
|
||||
// separated because there may be a need to postpone IP Address
|
||||
// assignment (emulation) or modify to use dynamic routing
|
||||
NS_LOG_INFO ("Add Static Routes.");
|
||||
PointToPointTopology::AddIpv4Routes(n0, n2, channel0);
|
||||
PointToPointTopology::AddIpv4Routes(n1, n2, channel1);
|
||||
PointToPointTopology::AddIpv4Routes(n2, n3, channel2);
|
||||
|
||||
// Create the OnOff application to send UDP datagrams of size
|
||||
// 210 bytes at a rate of 448 Kb/s
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint16_t port = 9; // Discard port (RFC 863)
|
||||
Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
|
||||
n0,
|
||||
InetSocketAddress ("10.1.3.2", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.0));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create an optional packet sink to receive these packets
|
||||
Ptr<PacketSink> sink = Create<PacketSink> (
|
||||
n3,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.0));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Create a similar flow from n3 to n1, starting at time 1.1 seconds
|
||||
ooff = Create<OnOffApplication> (
|
||||
n3,
|
||||
InetSocketAddress ("10.1.2.1", port),
|
||||
"Udp",
|
||||
ConstantVariable(1),
|
||||
ConstantVariable(0));
|
||||
// Start the application
|
||||
ooff->Start(Seconds(1.1));
|
||||
ooff->Stop (Seconds(10.0));
|
||||
|
||||
// Create a packet sink to receive these packets
|
||||
sink = Create<PacketSink> (
|
||||
n1,
|
||||
InetSocketAddress (Ipv4Address::GetAny (), port),
|
||||
"Udp");
|
||||
// Start the sink
|
||||
sink->Start (Seconds (1.1));
|
||||
sink->Stop (Seconds (10.0));
|
||||
|
||||
// Here, finish off packet routing configuration
|
||||
// This will likely set by some global StaticRouting object in the future
|
||||
NS_LOG_INFO ("Set Default Routes.");
|
||||
Ptr<Ipv4> ipv4;
|
||||
ipv4 = n0->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
|
||||
ipv4 = n3->QueryInterface<Ipv4> (Ipv4::iid);
|
||||
ipv4->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
|
||||
|
||||
//
|
||||
// Error model
|
||||
//
|
||||
// We want to add an error model to node 3's NetDevice
|
||||
// We can obtain a handle to the NetDevice via the channel and node
|
||||
// pointers
|
||||
Ptr<PointToPointNetDevice> nd3 = PointToPointTopology::GetNetDevice
|
||||
(n3, channel2);
|
||||
// Create an ErrorModel based on the implementation (constructor)
|
||||
// specified by the default classId
|
||||
Ptr<ErrorModel> em = ErrorModel::CreateDefault ();
|
||||
NS_ASSERT (em != 0);
|
||||
// Now, query interface on the resulting em pointer to see if a
|
||||
// RateErrorModel interface exists. If so, set the packet error rate
|
||||
Ptr<RateErrorModel> bem = em->QueryInterface<RateErrorModel>
|
||||
(RateErrorModel::iid);
|
||||
if (bem)
|
||||
{
|
||||
bem->SetRandomVariable (UniformVariable ());
|
||||
bem->SetRate (0.001);
|
||||
}
|
||||
nd3->AddReceiveErrorModel (em);
|
||||
|
||||
// Now, let's use the ListErrorModel and explicitly force a loss
|
||||
// of the packets with pkt-uids = 11 and 17 on node 2, device 0
|
||||
Ptr<PointToPointNetDevice> nd2 = PointToPointTopology::GetNetDevice
|
||||
(n2, channel0);
|
||||
std::list<uint32_t> sampleList;
|
||||
sampleList.push_back (11);
|
||||
sampleList.push_back (17);
|
||||
// This time, we'll explicitly create the error model we want
|
||||
Ptr<ListErrorModel> pem = Create<ListErrorModel> ();
|
||||
pem->SetList (sampleList);
|
||||
nd2->AddReceiveErrorModel (pem);
|
||||
|
||||
// Configure tracing of all enqueue, dequeue, and NetDevice receive events
|
||||
// Trace output will be sent to the simple-error-model.tr file
|
||||
NS_LOG_INFO ("Configure Tracing.");
|
||||
AsciiTrace asciitrace ("simple-error-model.tr");
|
||||
asciitrace.TraceAllQueues ();
|
||||
asciitrace.TraceAllNetDeviceRx ();
|
||||
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
@@ -14,6 +14,10 @@ def build(bld):
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'simple-point-to-point.cc'
|
||||
|
||||
obj = bld.create_ns3_program('simple-error-model',
|
||||
['point-to-point', 'internet-node'])
|
||||
obj.source = 'simple-error-model.cc'
|
||||
|
||||
obj = bld.create_ns3_program('csma-one-subnet',
|
||||
['csma', 'internet-node'])
|
||||
obj.source = 'csma-one-subnet.cc'
|
||||
|
||||
300
src/common/error-model.cc
Normal file
300
src/common/error-model.cc
Normal file
@@ -0,0 +1,300 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 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
|
||||
*
|
||||
* Author: Tom Henderson <tomhend@u.washington.edu>
|
||||
* This code has been ported from ns-2 (queue/errmodel.{cc,h}
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "error-model.h"
|
||||
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/assert.h"
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/random-variable.h"
|
||||
#include "ns3/default-value.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("ErrorModel");
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
static ClassIdDefaultValue g_classIdErrorModelDefaultValue ("ErrorModel",
|
||||
"Error Model", ErrorModel::iid, "RateErrorModel");
|
||||
|
||||
const InterfaceId ErrorModel::iid =
|
||||
MakeInterfaceId ("ErrorModel", Object::iid);
|
||||
|
||||
ErrorModel::ErrorModel () :
|
||||
m_enable (true)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
SetInterfaceId (ErrorModel::iid);
|
||||
}
|
||||
|
||||
ErrorModel::~ErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
Ptr<ErrorModel>
|
||||
ErrorModel::CreateDefault (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
ClassId classId = g_classIdErrorModelDefaultValue.GetValue ();
|
||||
Ptr<ErrorModel> em = ComponentManager::Create<ErrorModel> (classId,
|
||||
ErrorModel::iid);
|
||||
return em;
|
||||
}
|
||||
|
||||
bool
|
||||
ErrorModel::IsCorrupt (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
bool result;
|
||||
// Insert any pre-conditions here
|
||||
result = DoCorrupt (p);
|
||||
// Insert any post-conditions here
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Reset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
DoReset ();
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Enable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_enable = true;
|
||||
}
|
||||
|
||||
void
|
||||
ErrorModel::Disable (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_enable = false;
|
||||
}
|
||||
|
||||
bool
|
||||
ErrorModel::IsEnabled (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_enable;
|
||||
}
|
||||
|
||||
//
|
||||
// RateErrorModel
|
||||
//
|
||||
|
||||
const InterfaceId RateErrorModel::iid =
|
||||
MakeInterfaceId ("RateErrorModel", ErrorModel::iid);
|
||||
|
||||
const ClassId RateErrorModel::cid =
|
||||
MakeClassId<RateErrorModel> ("RateErrorModel", ErrorModel::iid,
|
||||
RateErrorModel::iid);
|
||||
|
||||
// Defaults for rate/size
|
||||
static NumericDefaultValue<double> g_defaultRateErrorModelErrorRate
|
||||
("RateErrorModelErrorRate", "The error rate for the error model", 0.0);
|
||||
|
||||
static EnumDefaultValue<enum ErrorUnit>
|
||||
g_defaultRateErrorModelErrorUnit ("RateErrorModelErrorUnit",
|
||||
"The error unit for this error model",
|
||||
EU_BYTE, "EU_BYTE",
|
||||
EU_PKT, "EU_PKT",
|
||||
EU_BIT, "EU_BIT",
|
||||
0, (void*)0);
|
||||
|
||||
RateErrorModel::RateErrorModel () :
|
||||
m_unit (g_defaultRateErrorModelErrorUnit.GetValue() ),
|
||||
m_rate (g_defaultRateErrorModelErrorRate.GetValue() )
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// Assume a uniform random variable if user does not specify
|
||||
m_ranvar = new UniformVariable ();
|
||||
SetInterfaceId (RateErrorModel::iid);
|
||||
}
|
||||
|
||||
RateErrorModel::~RateErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
delete m_ranvar;
|
||||
}
|
||||
|
||||
enum ErrorUnit
|
||||
RateErrorModel::GetUnit (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_unit;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetUnit (enum ErrorUnit error_unit)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_unit = error_unit;
|
||||
}
|
||||
|
||||
double
|
||||
RateErrorModel::GetRate (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_rate;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetRate (double rate)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_rate = rate;
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::SetRandomVariable (const RandomVariable &ranvar)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
delete m_ranvar;
|
||||
m_ranvar = ranvar.Copy ();
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorrupt (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
if (!m_enable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (m_unit)
|
||||
{
|
||||
case EU_PKT:
|
||||
return DoCorruptPkt (p);
|
||||
case EU_BYTE:
|
||||
return DoCorruptByte (p);
|
||||
case EU_BIT:
|
||||
return DoCorruptBit (p);
|
||||
default:
|
||||
NS_ASSERT_MSG (false, "m_unit not supported yet");
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptPkt (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return (m_ranvar->GetValue () < m_rate);
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptByte (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// compute pkt error rate, assume uniformly distributed byte error
|
||||
double per = 1 - pow (1.0 - m_rate, p.GetSize ());
|
||||
return (m_ranvar->GetValue () < per);
|
||||
}
|
||||
|
||||
bool
|
||||
RateErrorModel::DoCorruptBit(Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
// compute pkt error rate, assume uniformly distributed bit error
|
||||
double per = 1 - pow (1.0 - m_rate, (8 * p.GetSize ()) );
|
||||
return (m_ranvar->GetValue () < per);
|
||||
}
|
||||
|
||||
void
|
||||
RateErrorModel::DoReset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
/* re-initialize any state; no-op for now */
|
||||
}
|
||||
|
||||
//
|
||||
// ListErrorModel
|
||||
//
|
||||
|
||||
const InterfaceId ListErrorModel::iid =
|
||||
MakeInterfaceId ("ListErrorModel", ErrorModel::iid);
|
||||
|
||||
const ClassId ListErrorModel::cid =
|
||||
MakeClassId<ListErrorModel> ("ListErrorModel", ErrorModel::iid,
|
||||
ListErrorModel::iid);
|
||||
|
||||
ListErrorModel::ListErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
SetInterfaceId (ListErrorModel::iid);
|
||||
}
|
||||
|
||||
ListErrorModel::~ListErrorModel ()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
std::list<uint32_t>
|
||||
ListErrorModel::GetList (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_packetList;
|
||||
}
|
||||
|
||||
void
|
||||
ListErrorModel::SetList (const std::list<uint32_t> &packetlist)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_packetList = packetlist;
|
||||
}
|
||||
|
||||
// When performance becomes a concern, the list provided could be
|
||||
// converted to a dynamically-sized array of uint32_t to avoid
|
||||
// list iteration below.
|
||||
bool
|
||||
ListErrorModel::DoCorrupt (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
if (!m_enable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
uint32_t uid = p.GetUid ();
|
||||
for (PacketListCI i = m_packetList.begin ();
|
||||
i != m_packetList.end (); i++)
|
||||
{
|
||||
if (uid == *i)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ListErrorModel::DoReset (void)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_packetList.clear();
|
||||
}
|
||||
|
||||
|
||||
} //namespace ns3
|
||||
236
src/common/error-model.h
Normal file
236
src/common/error-model.h
Normal file
@@ -0,0 +1,236 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2007 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
|
||||
*
|
||||
* Author: Tom Henderson <tomhend@u.washington.edu>
|
||||
* This code has been ported from ns-2 (queue/errmodel.{cc,h}
|
||||
*/
|
||||
#ifndef ERROR_MODEL_H
|
||||
#define ERROR_MODEL_H
|
||||
|
||||
#include <list>
|
||||
#include "ns3/object.h"
|
||||
#include "ns3/component-manager.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class Packet;
|
||||
class RandomVariable;
|
||||
|
||||
/**
|
||||
* \brief General error model that can be used to corrupt packets
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* It is part of the Object framework and can be aggregated to
|
||||
* other ns3 objects and handled by the Ptr class.
|
||||
*
|
||||
* The main method is IsCorrupt(Packet& p) which returns true if
|
||||
* the packet is to be corrupted according to the underlying model.
|
||||
* Depending on the error model, the packet itself may have its packet
|
||||
* data buffer errored or not, or side information may be returned to
|
||||
* the client in the form of a packet tag.
|
||||
* The object can have state (resettable by Reset()).
|
||||
* The object can also be enabled and disabled via two public member functions.
|
||||
*
|
||||
* Typical code (simplified) to use an ErrorModel may look something like
|
||||
* this:
|
||||
* \code
|
||||
* Ptr<ErrorModel> rem = Create<RateErrorModel> ();
|
||||
* rem->SetRandomVariable (UniformVariable ());
|
||||
* rem->SetRate (0.001);
|
||||
* ...
|
||||
* Packet p;
|
||||
* if (rem->IsCorrupt (p))
|
||||
* {
|
||||
* dropTrace(p);
|
||||
* } else {
|
||||
* Forward (p);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* Two practical error models, a ListErrorModel and a RateErrorModel,
|
||||
* are currently implemented.
|
||||
*/
|
||||
class ErrorModel : public Object
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
/**
|
||||
* A factory method to generate a preconfigured default ErrorModel for use
|
||||
* \return an ErrorModel smart pointer that is the default ErrorModel
|
||||
* type defined
|
||||
*/
|
||||
static Ptr<ErrorModel> CreateDefault (void);
|
||||
|
||||
ErrorModel ();
|
||||
virtual ~ErrorModel ();
|
||||
|
||||
/**
|
||||
* \returns true if the Packet is to be considered as errored/corrupted
|
||||
* \param pkt Packet to apply error model to
|
||||
*/
|
||||
bool IsCorrupt (Packet& pkt);
|
||||
/**
|
||||
* Reset any state associated with the error model
|
||||
*/
|
||||
void Reset (void);
|
||||
/**
|
||||
* Enable the error model
|
||||
*/
|
||||
void Enable (void);
|
||||
/**
|
||||
* Disable the error model
|
||||
*/
|
||||
void Disable (void);
|
||||
/**
|
||||
* \return true if error model is enabled; false otherwise
|
||||
*/
|
||||
bool IsEnabled (void) const;
|
||||
|
||||
protected:
|
||||
bool m_enable;
|
||||
|
||||
private:
|
||||
/*
|
||||
* These methods must be implemented by subclasses
|
||||
*/
|
||||
virtual bool DoCorrupt (Packet&) = 0;
|
||||
virtual void DoReset (void) = 0;
|
||||
|
||||
};
|
||||
|
||||
enum ErrorUnit
|
||||
{
|
||||
EU_BIT,
|
||||
EU_BYTE,
|
||||
EU_PKT
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Determine which packets are errored corresponding to an underlying
|
||||
* distribution, rate, and unit.
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* The two parameters that govern the behavior are the rate (or
|
||||
* equivalently, the mean duration/spacing between errors), and the
|
||||
* unit (which may be per-bit, per-byte, and per-packet).
|
||||
* Users can optionally provide a RandomVariable object; the default
|
||||
* is to use a Uniform(0,1) distribution.
|
||||
|
||||
* Reset() on this model will do nothing
|
||||
*
|
||||
* IsCorrupt() will not modify the packet data buffer
|
||||
*/
|
||||
class RateErrorModel : public ErrorModel
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
|
||||
RateErrorModel ();
|
||||
virtual ~RateErrorModel ();
|
||||
|
||||
/**
|
||||
* \returns the ErrorUnit being used by the underlying model
|
||||
*/
|
||||
enum ErrorUnit GetUnit (void) const;
|
||||
/**
|
||||
* \param error_unit the ErrorUnit to be used by the underlying model
|
||||
*/
|
||||
void SetUnit (enum ErrorUnit error_unit);
|
||||
|
||||
/**
|
||||
* \returns the error rate being applied by the model
|
||||
*/
|
||||
double GetRate (void) const;
|
||||
/**
|
||||
* \param rate the error rate to be used by the model
|
||||
*/
|
||||
void SetRate (double rate);
|
||||
|
||||
/**
|
||||
* \param ranvar A random variable distribution to generate random variates
|
||||
*/
|
||||
void SetRandomVariable (const RandomVariable &ranvar);
|
||||
|
||||
private:
|
||||
virtual bool DoCorrupt (Packet& p);
|
||||
virtual bool DoCorruptPkt (Packet& p);
|
||||
virtual bool DoCorruptByte (Packet& p);
|
||||
virtual bool DoCorruptBit (Packet& p);
|
||||
virtual void DoReset (void);
|
||||
|
||||
enum ErrorUnit m_unit;
|
||||
double m_rate;
|
||||
|
||||
RandomVariable* m_ranvar;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Provide a list of Packet uids to corrupt
|
||||
*
|
||||
* This object is used to flag packets as being lost/errored or not.
|
||||
* A note on performance: the list is assumed to be unordered, and
|
||||
* in general, Packet uids received may be unordered. Therefore,
|
||||
* each call to IsCorrupt() will result in a walk of the list with
|
||||
* the present underlying implementation.
|
||||
*
|
||||
* Note also that if one wants to target multiple packets from looking
|
||||
* at an (unerrored) trace file, the act of erroring a given packet may
|
||||
* cause subsequent packet uids to change. For instance, suppose one wants
|
||||
* to error packets 11 and 17 on a given device. It may be that erroring
|
||||
* packet 11 will cause the subsequent uid stream to change and 17 may no
|
||||
* longer correspond to the second packet that one wants to lose. Therefore,
|
||||
* be advised that it might take some trial and error to select the
|
||||
* right uids when multiple are provided.
|
||||
*
|
||||
* Reset() on this model will clear the list
|
||||
*
|
||||
* IsCorrupt() will not modify the packet data buffer
|
||||
*/
|
||||
class ListErrorModel : public ErrorModel
|
||||
{
|
||||
public:
|
||||
static const InterfaceId iid;
|
||||
static const ClassId cid;
|
||||
ListErrorModel ();
|
||||
virtual ~ListErrorModel ();
|
||||
|
||||
/**
|
||||
* \return a copy of the underlying list
|
||||
*/
|
||||
std::list<uint32_t> GetList (void) const;
|
||||
/**
|
||||
* \param packetlist The list of packet uids to error.
|
||||
*
|
||||
* This method overwrites any previously provided list.
|
||||
*/
|
||||
void SetList (const std::list<uint32_t> &packetlist);
|
||||
|
||||
private:
|
||||
virtual bool DoCorrupt (Packet& p);
|
||||
virtual void DoReset (void);
|
||||
|
||||
typedef std::list<uint32_t> PacketList;
|
||||
typedef std::list<uint32_t>::const_iterator PacketListCI;
|
||||
|
||||
PacketList m_packetList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} //namespace ns3
|
||||
#endif
|
||||
@@ -13,6 +13,7 @@ def build(bld):
|
||||
'tag-registry.cc',
|
||||
'pcap-writer.cc',
|
||||
'data-rate.cc',
|
||||
'error-model.cc',
|
||||
]
|
||||
|
||||
headers = bld.create_obj('ns3header')
|
||||
@@ -29,4 +30,5 @@ def build(bld):
|
||||
'packet-metadata.h',
|
||||
'pcap-writer.h',
|
||||
'data-rate.h',
|
||||
'error-model.h',
|
||||
]
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "ns3/ethernet-header.h"
|
||||
#include "ns3/ethernet-trailer.h"
|
||||
#include "ns3/llc-snap-header.h"
|
||||
#include "ns3/error-model.h"
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
|
||||
|
||||
@@ -82,7 +83,8 @@ CsmaTraceType::Get (void) const
|
||||
|
||||
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
|
||||
: NetDevice (node, Mac48Address::Allocate ()),
|
||||
m_bps (DataRate (0xffffffff))
|
||||
m_bps (DataRate (0xffffffff)),
|
||||
m_receiveErrorModel (0)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << node << ")");
|
||||
@@ -93,7 +95,8 @@ CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
|
||||
CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Mac48Address addr,
|
||||
CsmaEncapsulationMode encapMode)
|
||||
: NetDevice(node, addr),
|
||||
m_bps (DataRate (0xffffffff))
|
||||
m_bps (DataRate (0xffffffff)),
|
||||
m_receiveErrorModel (0)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << node << ")");
|
||||
@@ -531,6 +534,15 @@ CsmaNetDevice::AddQueue (Ptr<Queue> q)
|
||||
m_queue = q;
|
||||
}
|
||||
|
||||
void CsmaNetDevice::AddReceiveErrorModel (Ptr<ErrorModel> em)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << em << ")");
|
||||
|
||||
m_receiveErrorModel = em;
|
||||
AddInterface (em);
|
||||
}
|
||||
|
||||
void
|
||||
CsmaNetDevice::Receive (const Packet& packet)
|
||||
{
|
||||
@@ -593,31 +605,41 @@ CsmaNetDevice::Receive (const Packet& packet)
|
||||
return;
|
||||
}
|
||||
|
||||
m_rxTrace (p);
|
||||
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (p) )
|
||||
{
|
||||
NS_LOG_LOGIC ("Dropping pkt due to error model ");
|
||||
m_dropTrace (packet);
|
||||
// Do not forward up; let this packet go
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rxTrace (p);
|
||||
//
|
||||
// protocol must be initialized to avoid a compiler warning in the RAW
|
||||
// case that breaks the optimized build.
|
||||
//
|
||||
uint16_t protocol = 0;
|
||||
uint16_t protocol = 0;
|
||||
|
||||
switch (m_encapMode)
|
||||
{
|
||||
case ETHERNET_V1:
|
||||
case IP_ARP:
|
||||
protocol = header.GetLengthType();
|
||||
break;
|
||||
case LLC: {
|
||||
LlcSnapHeader llc;
|
||||
p.RemoveHeader (llc);
|
||||
protocol = llc.GetType ();
|
||||
} break;
|
||||
case RAW:
|
||||
NS_ASSERT (false);
|
||||
break;
|
||||
switch (m_encapMode)
|
||||
{
|
||||
case ETHERNET_V1:
|
||||
case IP_ARP:
|
||||
protocol = header.GetLengthType();
|
||||
break;
|
||||
case LLC:
|
||||
{
|
||||
LlcSnapHeader llc;
|
||||
p.RemoveHeader (llc);
|
||||
protocol = llc.GetType ();
|
||||
}
|
||||
break;
|
||||
case RAW:
|
||||
NS_ASSERT (false);
|
||||
break;
|
||||
}
|
||||
ForwardUp (p, protocol, header.GetSource ());
|
||||
return;
|
||||
}
|
||||
|
||||
ForwardUp (p, protocol, header.GetSource ());
|
||||
return;
|
||||
}
|
||||
|
||||
Address
|
||||
@@ -687,4 +709,5 @@ CsmaNetDevice::DoGetChannel(void) const
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace ns3 {
|
||||
|
||||
class Queue;
|
||||
class CsmaChannel;
|
||||
class ErrorModel;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of trace source from a CsmaNetDevice
|
||||
@@ -192,6 +193,16 @@ enum CsmaEncapsulationMode {
|
||||
* ownership.
|
||||
*/
|
||||
void AddQueue (Ptr<Queue> queue);
|
||||
/**
|
||||
* Attach a receive ErrorModel to the CsmaNetDevice.
|
||||
*
|
||||
* The CsmaNetDevice may optionally include an ErrorModel in
|
||||
* the packet receive chain.
|
||||
*
|
||||
* @see ErrorModel
|
||||
* @param em a pointer to the ErrorModel
|
||||
*/
|
||||
void AddReceiveErrorModel(Ptr<ErrorModel> em);
|
||||
/**
|
||||
* Receive a packet from a connected CsmaChannel.
|
||||
*
|
||||
@@ -453,6 +464,12 @@ private:
|
||||
* @see class DropTailQueue
|
||||
*/
|
||||
Ptr<Queue> m_queue;
|
||||
|
||||
/**
|
||||
* Error model for receive packet events
|
||||
*/
|
||||
Ptr<ErrorModel> m_receiveErrorModel;
|
||||
|
||||
/**
|
||||
* NOT TESTED
|
||||
* The trace source for the packet reception events that the device can
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ns3/composite-trace-resolver.h"
|
||||
#include "ns3/mac48-address.h"
|
||||
#include "ns3/llc-snap-header.h"
|
||||
#include "ns3/error-model.h"
|
||||
#include "point-to-point-net-device.h"
|
||||
#include "point-to-point-channel.h"
|
||||
|
||||
@@ -38,14 +39,28 @@ DataRateDefaultValue PointToPointNetDevice::g_defaultRate(
|
||||
"The default data rate for point to point links",
|
||||
DataRate ("10Mb/s"));
|
||||
|
||||
PointToPointTraceType::PointToPointTraceType ()
|
||||
PointToPointTraceType::PointToPointTraceType (enum Type type)
|
||||
: m_type (type)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
PointToPointTraceType::PointToPointTraceType ()
|
||||
: m_type (RX)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
}
|
||||
|
||||
void
|
||||
PointToPointTraceType::Print (std::ostream &os) const
|
||||
{
|
||||
os << "dev-rx";
|
||||
switch (m_type) {
|
||||
case RX:
|
||||
os << "dev-rx";
|
||||
break;
|
||||
case DROP:
|
||||
os << "dev-drop";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
@@ -63,6 +78,12 @@ PointToPointTraceType::GetTypeName (void) const
|
||||
return "ns3::PointToPointTraceType";
|
||||
}
|
||||
|
||||
enum PointToPointTraceType::Type
|
||||
PointToPointTraceType::Get (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
return m_type;
|
||||
}
|
||||
|
||||
PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
|
||||
const DataRate& rate)
|
||||
@@ -73,7 +94,9 @@ PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
|
||||
m_tInterframeGap (Seconds(0)),
|
||||
m_channel (0),
|
||||
m_queue (0),
|
||||
m_rxTrace ()
|
||||
m_rxTrace (),
|
||||
m_dropTrace (),
|
||||
m_receiveErrorModel (0)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << node << ")");
|
||||
@@ -94,6 +117,7 @@ PointToPointNetDevice::~PointToPointNetDevice()
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
m_queue = 0;
|
||||
m_receiveErrorModel = 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -221,7 +245,12 @@ PointToPointNetDevice::GetTraceResolver (void) const
|
||||
TraceDoc ("receive MAC packet",
|
||||
"const Packet &", "packet received"),
|
||||
m_rxTrace,
|
||||
PointToPointTraceType ());
|
||||
PointToPointTraceType (PointToPointTraceType::RX));
|
||||
resolver->AddSource ("drop",
|
||||
TraceDoc ("drop MAC packet",
|
||||
"const Packet &", "packet dropped"),
|
||||
m_dropTrace,
|
||||
PointToPointTraceType (PointToPointTraceType::DROP));
|
||||
resolver->SetParentResolver (NetDevice::GetTraceResolver ());
|
||||
return resolver;
|
||||
}
|
||||
@@ -262,6 +291,15 @@ void PointToPointNetDevice::AddQueue (Ptr<Queue> q)
|
||||
m_queue = q;
|
||||
}
|
||||
|
||||
void PointToPointNetDevice::AddReceiveErrorModel (Ptr<ErrorModel> em)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
NS_LOG_PARAM ("(" << em << ")");
|
||||
|
||||
m_receiveErrorModel = em;
|
||||
AddInterface (em);
|
||||
}
|
||||
|
||||
void PointToPointNetDevice::Receive (Packet& p)
|
||||
{
|
||||
NS_LOG_FUNCTION;
|
||||
@@ -269,9 +307,17 @@ void PointToPointNetDevice::Receive (Packet& p)
|
||||
uint16_t protocol = 0;
|
||||
Packet packet = p;
|
||||
|
||||
m_rxTrace (packet);
|
||||
ProcessHeader(packet, protocol);
|
||||
ForwardUp (packet, protocol, GetBroadcast ());
|
||||
if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (p) )
|
||||
{
|
||||
m_dropTrace (packet);
|
||||
// Do not forward up; let this packet go
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rxTrace (packet);
|
||||
ProcessHeader(packet, protocol);
|
||||
ForwardUp (packet, protocol, GetBroadcast ());
|
||||
}
|
||||
}
|
||||
|
||||
Ptr<Queue> PointToPointNetDevice::GetQueue(void) const
|
||||
|
||||
@@ -37,6 +37,7 @@ namespace ns3 {
|
||||
|
||||
class Queue;
|
||||
class PointToPointChannel;
|
||||
class ErrorModel;
|
||||
|
||||
/**
|
||||
* \brief hold in a TraceContext the type of trace source from a PointToPointNetDevice
|
||||
@@ -44,10 +45,21 @@ class PointToPointChannel;
|
||||
class PointToPointTraceType : public TraceContextElement
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
RX,
|
||||
DROP
|
||||
};
|
||||
PointToPointTraceType (enum Type type);
|
||||
PointToPointTraceType ();
|
||||
void Print (std::ostream &os) const;
|
||||
static uint16_t GetUid (void);
|
||||
std::string GetTypeName (void) const;
|
||||
/**
|
||||
* \returns the type of the trace source which generated an event.
|
||||
*/
|
||||
enum Type Get (void) const;
|
||||
private:
|
||||
enum Type m_type;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -133,6 +145,16 @@ public:
|
||||
* ownership.
|
||||
*/
|
||||
void AddQueue (Ptr<Queue> queue);
|
||||
/**
|
||||
* Attach a receive ErrorModel to the PointToPointNetDevice.
|
||||
*
|
||||
* The PointToPointNetDevice may optionally include an ErrorModel in
|
||||
* the packet receive chain.
|
||||
*
|
||||
* @see ErrorModel
|
||||
* @param em a pointer to the ErrorModel
|
||||
*/
|
||||
void AddReceiveErrorModel(Ptr<ErrorModel> em);
|
||||
/**
|
||||
* Receive a packet from a connected PointToPointChannel.
|
||||
*
|
||||
@@ -288,11 +310,23 @@ private:
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
CallbackTraceSource<const Packet &> m_rxTrace;
|
||||
/**
|
||||
* The trace source for the packet drop events that the device can
|
||||
* fire.
|
||||
*
|
||||
* @see class CallBackTraceSource
|
||||
* @see class TraceResolver
|
||||
*/
|
||||
CallbackTraceSource<const Packet &> m_dropTrace;
|
||||
/**
|
||||
* Default data rate. Used for all newly created p2p net devices
|
||||
*/
|
||||
static DataRateDefaultValue g_defaultRate;
|
||||
|
||||
/**
|
||||
* Error model for receive packet events
|
||||
*/
|
||||
Ptr<ErrorModel> m_receiveErrorModel;
|
||||
};
|
||||
|
||||
}; // namespace ns3
|
||||
|
||||
Reference in New Issue
Block a user