--- a/src/node/simple-channel.cc Wed Mar 03 05:56:47 2010 -0800
+++ b/src/node/simple-channel.cc Fri Mar 05 11:56:10 2010 -0800
@@ -22,6 +22,9 @@
#include "ns3/simulator.h"
#include "ns3/packet.h"
#include "ns3/node.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("SimpleChannel");
namespace ns3 {
@@ -43,6 +46,7 @@
Mac48Address to, Mac48Address from,
Ptr<SimpleNetDevice> sender)
{
+ NS_LOG_FUNCTION (p << protocol << to << from << sender);
for (std::vector<Ptr<SimpleNetDevice> >::const_iterator i = m_devices.begin (); i != m_devices.end (); ++i)
{
Ptr<SimpleNetDevice> tmp = *i;
--- a/src/node/simple-net-device.cc Wed Mar 03 05:56:47 2010 -0800
+++ b/src/node/simple-net-device.cc Fri Mar 05 11:56:10 2010 -0800
@@ -21,6 +21,12 @@
#include "simple-channel.h"
#include "node.h"
#include "ns3/packet.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/error-model.h"
+#include "ns3/trace-source-accessor.h"
+
+NS_LOG_COMPONENT_DEFINE ("SimpleNetDevice");
namespace ns3 {
@@ -30,6 +36,14 @@
static TypeId tid = TypeId ("ns3::SimpleNetDevice")
.SetParent<NetDevice> ()
.AddConstructor<SimpleNetDevice> ()
+ .AddAttribute ("ReceiveErrorModel",
+ "The receiver error model used to simulate packet loss",
+ PointerValue (),
+ MakePointerAccessor (&SimpleNetDevice::m_receiveErrorModel),
+ MakePointerChecker<ErrorModel> ())
+ .AddTraceSource ("PhyRxDrop",
+ "Trace source indicating a packet has been dropped by the device during reception",
+ MakeTraceSourceAccessor (&SimpleNetDevice::m_phyRxDropTrace))
;
return tid;
}
@@ -45,7 +59,15 @@
SimpleNetDevice::Receive (Ptr<Packet> packet, uint16_t protocol,
Mac48Address to, Mac48Address from)
{
+ NS_LOG_FUNCTION (packet << protocol << to << from);
NetDevice::PacketType packetType;
+
+ if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
+ {
+ m_phyRxDropTrace (packet);
+ return;
+ }
+
if (to == m_address)
{
packetType = NetDevice::PACKET_HOST;
@@ -76,6 +98,12 @@
m_channel->Add (this);
}
+void
+SimpleNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
+{
+ m_receiveErrorModel = em;
+}
+
void
SimpleNetDevice::SetIfIndex(const uint32_t index)
{
@@ -164,6 +192,7 @@
bool
SimpleNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
{
+ NS_LOG_FUNCTION (packet << dest << protocolNumber);
Mac48Address to = Mac48Address::ConvertFrom (dest);
m_channel->Send (packet, protocolNumber, to, m_address, this);
return true;
@@ -203,6 +232,7 @@
{
m_channel = 0;
m_node = 0;
+ m_receiveErrorModel = 0;
NetDevice::DoDispose ();
}
--- a/src/node/simple-net-device.h Wed Mar 03 05:56:47 2010 -0800
+++ b/src/node/simple-net-device.h Fri Mar 05 11:56:10 2010 -0800
@@ -24,14 +24,21 @@
#include "mac48-address.h"
#include <stdint.h>
#include <string>
+#include "ns3/traced-callback.h"
namespace ns3 {
class SimpleChannel;
class Node;
+class ErrorModel;
/**
* \ingroup netdevice
+ *
+ * This device does not have a helper and assumes 48-bit mac addressing;
+ * the default address assigned to each device is zero, so you must
+ * assign a real address to use it. There is also the possibility to
+ * add an ErrorModel if you want to force losses on the device.
*
* \brief simple net device for simple things and testing
*/
@@ -44,6 +51,17 @@
void Receive (Ptr<Packet> packet, uint16_t protocol, Mac48Address to, Mac48Address from);
void SetChannel (Ptr<SimpleChannel> channel);
+ /**
+ * Attach a receive ErrorModel to the SimpleNetDevice.
+ *
+ * The SimpleNetDevice may optionally include an ErrorModel in
+ * the packet receive chain.
+ *
+ * \see ErrorModel
+ * \param em Ptr to the ErrorModel.
+ */
+ void SetReceiveErrorModel(Ptr<ErrorModel> em);
+
// inherited from NetDevice base class.
virtual void SetIfIndex(const uint32_t index);
virtual uint32_t GetIfIndex(void) const;
@@ -82,6 +100,16 @@
uint16_t m_mtu;
uint32_t m_ifIndex;
Mac48Address m_address;
+ Ptr<ErrorModel> m_receiveErrorModel;
+ /**
+ * The trace source fired when the phy layer drops a packet it has received
+ * due to the error model being active. Although SimpleNetDevice doesn't
+ * really have a Phy model, we choose this trace source name for alignment
+ * with other trace sources.
+ *
+ * \see class CallBackTraceSource
+ */
+ TracedCallback<Ptr<const Packet> > m_phyRxDropTrace;
};
} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/error-model-test-suite.cc Fri Mar 05 11:56:10 2010 -0800
@@ -0,0 +1,135 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "ns3/test.h"
+#include "ns3/simple-net-device.h"
+#include "ns3/simple-channel.h"
+#include "ns3/address.h"
+#include "ns3/mac48-address.h"
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/node.h"
+#include "ns3/simulator.h"
+#include "ns3/error-model.h"
+#include "ns3/pointer.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
+
+using namespace ns3;
+
+static void SendPacket (int num, Ptr<NetDevice> device, Address& addr)
+{
+ for (int i = 0; i < num; i++)
+ {
+ Ptr<Packet> pkt = Create<Packet> (1000); // 1000 dummy bytes of data
+ device->Send (pkt, addr, 0);
+ }
+}
+
+// Two nodes, two devices, one channel
+static void BuildSimpleTopology (Ptr<Node> a, Ptr<Node> b, Ptr<SimpleNetDevice> input, Ptr<SimpleNetDevice> output, Ptr<SimpleChannel> channel)
+{
+ a->AddDevice (input);
+ b->AddDevice (output);
+ input->SetAddress (Mac48Address::Allocate ());
+ input->SetChannel (channel);
+ input->SetNode (a);
+ output->SetChannel (channel);
+ output->SetNode (b);
+ output->SetAddress (Mac48Address::Allocate ());
+}
+
+class ErrorModelSimple : public TestCase
+{
+public:
+ ErrorModelSimple ();
+ virtual ~ErrorModelSimple ();
+
+private:
+ virtual bool DoRun (void);
+ bool Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr);
+ void DropEvent (Ptr<const Packet> p);
+ uint32_t m_count;
+ uint32_t m_drops;
+};
+
+// Add some help text to this case to describe what it is intended to test
+ErrorModelSimple::ErrorModelSimple ()
+ : TestCase ("ErrorModel and PhyRxDrop trace for SimpleNetDevice"), m_count (0), m_drops (0)
+{
+}
+
+ErrorModelSimple::~ErrorModelSimple ()
+{
+}
+
+bool
+ErrorModelSimple::Receive (Ptr<NetDevice> nd, Ptr<const Packet> p, uint16_t protocol, const Address& addr)
+{
+ m_count++;
+ return true;
+}
+
+void
+ErrorModelSimple::DropEvent (Ptr<const Packet> p)
+{
+ m_drops++;
+}
+
+bool
+ErrorModelSimple::DoRun (void)
+{
+ bool retval = false;
+ // Set some arbitrary deterministic values
+ SeedManager::SetSeed (7);
+ SeedManager::SetRun (5);
+
+ Ptr<Node> a = CreateObject<Node> ();
+ Ptr<Node> b = CreateObject<Node> ();
+
+ Ptr<SimpleNetDevice> input = CreateObject<SimpleNetDevice> ();
+ Ptr<SimpleNetDevice> output = CreateObject<SimpleNetDevice> ();
+ Ptr<SimpleChannel> channel = CreateObject<SimpleChannel> ();
+ BuildSimpleTopology (a, b, input, output, channel);
+
+ output->SetReceiveCallback (MakeCallback (&ErrorModelSimple::Receive, this));
+
+ Ptr<RateErrorModel> em = CreateObjectWithAttributes<RateErrorModel> ("RanVar", RandomVariableValue (UniformVariable (0.0, 1.0)));
+ em->SetAttribute ("ErrorRate", DoubleValue (0.001));
+ em->SetAttribute ("ErrorUnit", StringValue ("EU_PKT"));
+
+ // The below hooks will cause drops and receptions to be counted
+ output->SetAttribute ("ReceiveErrorModel", PointerValue (em));
+ output->TraceConnectWithoutContext ("PhyRxDrop", MakeCallback (&ErrorModelSimple::DropEvent, this));
+
+ // Send 10000 packets
+ Simulator::Schedule (Seconds (0), &SendPacket, 10000, input, output->GetAddress());
+
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ // For this combination of values, we expect about 1 packet in 1000 to be
+ // dropped. For this specific RNG stream, we see 9992 receptions and 8 drops
+ if (m_count != 9992 || m_drops != 8)
+ {
+ retval = true;
+ }
+ return retval;
+}
+
+// This is the start of an error model test suite. For starters, this is
+// just testing that the SimpleNetDevice is working but this can be
+// extended to many more test cases in the future
+class ErrorModelTestSuite : public TestSuite
+{
+public:
+ ErrorModelTestSuite ();
+};
+
+ErrorModelTestSuite::ErrorModelTestSuite ()
+ : TestSuite ("error-model", BVT)
+{
+ AddTestCase (new ErrorModelSimple);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+ErrorModelTestSuite errorModelTestSuite;
--- a/src/test/wscript Wed Mar 03 05:56:47 2010 -0800
+++ b/src/test/wscript Fri Mar 05 11:56:10 2010 -0800
@@ -7,6 +7,7 @@
test = bld.create_ns3_module('test', ['core'])
test.source = [
'sample-test-suite.cc',
+ 'error-model-test-suite.cc',
]
headers = bld.new_task_gen('ns3header')