Add src/common/error-model implementation and example script, and add to NetDevices
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-error-model.cc Wed Nov 14 20:40:05 2007 -0800
@@ -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.");
+}
--- a/examples/wscript Thu Nov 08 12:39:21 2007 +0100
+++ b/examples/wscript Wed Nov 14 20:40:05 2007 -0800
@@ -14,6 +14,10 @@
['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'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/error-model.cc Wed Nov 14 20:40:05 2007 -0800
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/error-model.h Wed Nov 14 20:40:05 2007 -0800
@@ -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
--- a/src/common/wscript Thu Nov 08 12:39:21 2007 +0100
+++ b/src/common/wscript Wed Nov 14 20:40:05 2007 -0800
@@ -13,6 +13,7 @@
'tag-registry.cc',
'pcap-writer.cc',
'data-rate.cc',
+ 'error-model.cc',
]
headers = bld.create_obj('ns3header')
@@ -29,4 +30,5 @@
'packet-metadata.h',
'pcap-writer.h',
'data-rate.h',
+ 'error-model.h',
]
--- a/src/devices/csma/csma-net-device.cc Thu Nov 08 12:39:21 2007 +0100
+++ b/src/devices/csma/csma-net-device.cc Wed Nov 14 20:40:05 2007 -0800
@@ -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 @@
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, 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 @@
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 @@
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 @@
return m_channel;
}
+
} // namespace ns3
--- a/src/devices/csma/csma-net-device.h Thu Nov 08 12:39:21 2007 +0100
+++ b/src/devices/csma/csma-net-device.h Wed Nov 14 20:40:05 2007 -0800
@@ -40,6 +40,7 @@
class Queue;
class CsmaChannel;
+class ErrorModel;
/**
* \brief hold in a TraceContext the type of trace source from a CsmaNetDevice
@@ -193,6 +194,16 @@
*/
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.
*
* The CsmaNetDevice receives packets from its connected channel
@@ -453,6 +464,12 @@
* @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
--- a/src/devices/point-to-point/point-to-point-net-device.cc Thu Nov 08 12:39:21 2007 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.cc Wed Nov 14 20:40:05 2007 -0800
@@ -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 @@
"The default data rate for point to point links",
DataRate ("10Mb/s"));
+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 @@
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 @@
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 @@
{
NS_LOG_FUNCTION;
m_queue = 0;
+ m_receiveErrorModel = 0;
}
void
@@ -221,7 +245,12 @@
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 @@
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 @@
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
--- a/src/devices/point-to-point/point-to-point-net-device.h Thu Nov 08 12:39:21 2007 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.h Wed Nov 14 20:40:05 2007 -0800
@@ -37,6 +37,7 @@
class Queue;
class PointToPointChannel;
+class ErrorModel;
/**
* \brief hold in a TraceContext the type of trace source from a PointToPointNetDevice
@@ -44,10 +45,21 @@
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;
};
/**
@@ -134,6 +146,16 @@
*/
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.
*
* The PointToPointNetDevice receives packets from its connected channel
@@ -288,11 +310,23 @@
* @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