Add src/common/error-model implementation and example script, and add to NetDevices

This commit is contained in:
Tom Henderson
2007-11-14 20:40:05 -08:00
parent c905f0658d
commit c3cbbcacd7
9 changed files with 930 additions and 28 deletions

View 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.");
}

View File

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

View File

@@ -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',
]

View File

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

View File

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

View File

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

View File

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