--- a/SConstruct Mon Mar 19 00:40:44 2007 -0700
+++ b/SConstruct Mon Mar 19 07:02:14 2007 -0700
@@ -24,6 +24,7 @@
'test.cc',
'random-variable.cc',
'rng-stream.cc',
+ 'object-container.cc',
])
env = Environment()
if env['PLATFORM'] == 'posix' or env['PLATFORM'] == 'darwin' or env['PLATFORM'] == 'cygwin':
@@ -48,7 +49,8 @@
'fatal-error.h',
'test.h',
'random-variable.h',
- 'rng-stream.h'
+ 'rng-stream.h',
+ 'object-container.h'
])
def config_core (env, config):
--- a/samples/ns-2/simple.cc Mon Mar 19 00:40:44 2007 -0700
+++ b/samples/ns-2/simple.cc Mon Mar 19 07:02:14 2007 -0700
@@ -37,6 +37,7 @@
// - Tracing of queues and packet receptions to file "out.tr"
#include <iostream>
+#include <fstream>
#include <string>
#include <cassert>
@@ -63,109 +64,85 @@
#include "ns3/udp-header.h"
#include "ns3/node-list.h"
#include "ns3/trace-root.h"
-
+#include "ns3/object-container.h"
#include "ns3/serial-topology.h"
using namespace ns3;
-class Tracer : public TraceWriter{
+class AsciiTrace
+{
public:
- Tracer ()
- {
- };
-
- Tracer (std::string const &filename)
- {
- Open(filename);
- };
-
- Tracer (char const *filename) : m_tracer(filename)
- {
- Open(filename);
- };
-
- ~Tracer () {};
+ AsciiTrace (std::string filename);
+ ~AsciiTrace ();
+ void TraceAllQueues (void);
+ void TraceAllNetDeviceRx (void);
+private:
+ void LogDevQueue (TraceContext const &context, const Packet &p);
+ void LogDevRx (TraceContext const &context, Packet &p);
+ std::ofstream m_os;
+};
- void LogNodeInterface (TraceContext const &context)
- {
- NodeList::NodeIndex nodeIndex;
- context.Get (nodeIndex);
- m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
- Ipv4::InterfaceIndex interfaceIndex;
- context.Get (interfaceIndex);
- m_filestr << "interface=" << interfaceIndex << " ";
- }
-
-
- void LogEnqueue (TraceContext const &context, const Packet &p)
- {
- m_filestr << "+ " << Simulator::Now().GetSeconds() << " ";
- LogNodeInterface (context);
- m_filestr << "pkt-uid=" << p.GetUid () << " ";
- //PrintLlcPacket (p, m_filestr);
- m_filestr << std::endl;
- }
+AsciiTrace::AsciiTrace (std::string filename)
+{
+ m_os.open (filename.c_str ());
+}
+AsciiTrace::~AsciiTrace ()
+{
+ m_os.close ();
+}
+void
+AsciiTrace::TraceAllQueues (void)
+{
+ TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
+ MakeCallback (&AsciiTrace::LogDevQueue, this));
+}
+void
+AsciiTrace::TraceAllNetDeviceRx (void)
+{
+ TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/rx",
+ MakeCallback (&AsciiTrace::LogDevRx, this));
+}
- void LogDequeue (TraceContext const &context, const Packet &p)
- {
- m_filestr << "- " << Simulator::Now().GetSeconds() << " ";
- LogNodeInterface (context);
- m_filestr << "pkt-uid=" << p.GetUid () << " ";
- //PrintLlcPacket (p, m_filestr);
- m_filestr << std::endl;
- }
- void LogDrop (TraceContext const &context, const Packet &p)
- {
- m_filestr << "d " << Simulator::Now().GetSeconds() << " ";
- LogNodeInterface (context);
- m_filestr << "pkt-uid=" << p.GetUid () << " ";
- //PrintLlcPacket (p, m_filestr);
- m_filestr << std::endl;
- }
-
- void PrintLlcPacket (Packet p, std::ostream &os)
- {
- LlcSnapHeader llc;
- p.Peek (llc);
- p.Remove (llc);
- switch (llc.GetType ())
- {
- case 0x0800: {
- Ipv4Header ipv4;
- p.Peek (ipv4);
- p.Remove (ipv4);
- if (ipv4.GetProtocol () == 17)
- {
- UdpHeader udp;
- p.Peek (udp);
- p.Remove (udp);
- os << "udp payload=" << p.GetSize ()
- << " from="<< ipv4.GetSource () << ":" << udp.GetSource ()
- << " to="<< ipv4.GetDestination () << ":" << udp.GetDestination ();
- }
- } break;
- case 0x0806: {
- ArpHeader arp;
- p.Peek (arp);
- p.Remove (arp);
- os << "arp ";
- if (arp.IsRequest ())
- {
- os << "request from=" << arp.GetSourceIpv4Address ()
- << ", for=" << arp.GetDestinationIpv4Address ();
- }
- else
- {
- os << "reply from=" << arp.GetSourceIpv4Address ()
- << ", for=" << arp.GetDestinationIpv4Address ();
- }
- } break;
- }
- }
-
-protected:
- TraceWriter m_tracer;
-};
+void
+AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &p)
+{
+ enum Queue::TraceType type;
+ context.Get (type);
+ switch (type)
+ {
+ case Queue::ENQUEUE:
+ m_os << "+ ";
+ break;
+ case Queue::DEQUEUE:
+ m_os << "- ";
+ break;
+ case Queue::DROP:
+ m_os << "d ";
+ break;
+ }
+ m_os << Simulator::Now ().GetSeconds () << " ";
+ NodeList::NodeIndex nodeIndex;
+ context.Get (nodeIndex);
+ m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+ Ipv4::InterfaceIndex interfaceIndex;
+ context.Get (interfaceIndex);
+ m_os << "interface=" << interfaceIndex << " ";
+ m_os << "pkt-uid=" << p.GetUid () << " ";
+ m_os << std::endl;
+}
+void
+AsciiTrace::LogDevRx (TraceContext const &context, Packet &p)
+{
+ m_os << "r " << Simulator::Now ().GetSeconds () << " ";
+ NodeList::NodeIndex nodeIndex;
+ context.Get (nodeIndex);
+ m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+ Ipv4::InterfaceIndex interfaceIndex;
+ context.Get (interfaceIndex);
+ m_os << "interface=" << interfaceIndex << " ";
+ m_os << "pkt-uid=" << p.GetUid () << " ";
+ m_os << std::endl;
+}
static void
@@ -230,6 +207,8 @@
DebugComponentEnable("SerialPhy");
#endif
+ ObjectContainer container;
+
// ** Here, some kind of factory or topology object will instantiates
// ** four identical nodes; for now, we just explicitly create them
InternetNode *n0 = new InternetNode();
@@ -237,6 +216,11 @@
InternetNode *n2 = new InternetNode();
InternetNode *n3 = new InternetNode();
+ container.Acquire (n0);
+ container.Acquire (n1);
+ container.Acquire (n2);
+ container.Acquire (n3);
+
NodeList::Add (n0);
NodeList::Add (n1);
NodeList::Add (n2);
@@ -247,17 +231,20 @@
n2->SetName(std::string("Node 2"));
n3->SetName(std::string("Node 3"));
- SerialChannel* ch1 = SerialTopology::AddSerialLink (
+ SerialChannel* ch1;
+ ch1 = SerialTopology::AddSerialLink (
n0, Ipv4Address("10.1.1.1"),
n2, Ipv4Address("10.1.1.2"),
5000000, MilliSeconds(2));
- SerialChannel* ch2 = SerialTopology::AddSerialLink (
+ SerialChannel* ch2;
+ ch2 = SerialTopology::AddSerialLink (
n1, Ipv4Address("10.1.2.1"),
n2, Ipv4Address("10.1.2.2"),
5000000, MilliSeconds(2));
- SerialChannel* ch3 = SerialTopology::AddSerialLink (
+ SerialChannel* ch3;
+ ch3 = SerialTopology::AddSerialLink (
n2, Ipv4Address("10.1.3.1"),
n3, Ipv4Address("10.1.3.2"),
1500000, MilliSeconds(10));
@@ -269,6 +256,11 @@
DatagramSocket *sink1 = new DatagramSocket(n1);
sink1->Bind (80);
+ container.Acquire (source0);
+ container.Acquire (source3);
+ container.Acquire (sink3);
+ container.Acquire (sink1);
+
source3->SetDefaultDestination (Ipv4Address ("10.1.2.1"), 80);
source0->SetDefaultDestination (Ipv4Address ("10.1.3.2"), 80);
@@ -276,18 +268,9 @@
n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
- Tracer tracer("out.tr");
- TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/enqueue",
- MakeCallback (&Tracer::LogEnqueue, &tracer));
- TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/dequeue",
- MakeCallback (&Tracer::LogDequeue, &tracer));
- TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/drop",
- MakeCallback (&Tracer::LogDrop, &tracer));
-#if 0
- TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/receive",
- MakeCallback (&Tracer::LogReceive, &tracer));
-#endif
-
+ AsciiTrace trace ("out.tr");
+ trace.TraceAllQueues ();
+ trace.TraceAllNetDeviceRx ();
PrintTraffic (sink3);
GenerateTraffic (source0, 100);
@@ -301,17 +284,6 @@
// The below deletes will be managed by future topology objects
// or containers or smart pointers
- delete n0;
- delete n1;
- delete n2;
- delete n3;
- delete ch1;
- delete ch2;
- delete ch3;
- delete source3;
- delete source0;
- delete sink3;
- delete sink1;
Simulator::Destroy ();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-container.cc Mon Mar 19 07:02:14 2007 -0700
@@ -0,0 +1,201 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "object-container.h"
+
+namespace ns3 {
+
+ObjectContainer::DeleterList ObjectContainer::m_deleterList;
+
+ObjectContainer::~ObjectContainer ()
+{
+ Cleanup ();
+}
+
+void
+ObjectContainer::Cleanup (void)
+{
+ for (List::iterator i = m_list.begin (); i != m_list.end (); i++)
+ {
+ uint32_t uid = i->first;
+ std::vector<void *> *vec = i->second;
+ ObjectDeleter deleter = LookupObjectDeleter (uid);
+ for (std::vector<void *>::iterator j = vec->begin ();
+ j != vec->end (); j++)
+ {
+ (deleter) (*j);
+ }
+ delete vec;
+ }
+ m_list.erase (m_list.begin (), m_list.end ());
+}
+
+uint32_t
+ObjectContainer::GetGlobalUid (void) const
+{
+ static uint32_t globalUid = 0;
+ globalUid ++;
+ return globalUid;
+}
+
+uint32_t
+ObjectContainer::RegisterUid (uint32_t uid, ObjectDeleter deleter) const
+{
+ for (DeleterList::iterator i = m_deleterList.begin ();
+ i != m_deleterList.end (); i++)
+ {
+ NS_ASSERT (i->first != uid);
+ }
+ m_deleterList.push_back (std::make_pair (uid, deleter));
+ return uid;
+}
+
+ObjectContainer::ObjectDeleter
+ObjectContainer::LookupObjectDeleter (uint32_t uid) const
+{
+ for (DeleterList::iterator i = m_deleterList.begin ();
+ i != m_deleterList.end (); i++)
+ {
+ if (i->first == uid)
+ {
+ return i->second;
+ }
+ }
+ NS_FATAL_ERROR ("unknown deleter requested.");
+ return 0;
+}
+
+}//namespace ns3
+
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+namespace ns3 {
+
+class A
+{
+public:
+ A () {}
+ ~A () {}
+};
+
+class WithCopy
+{
+public:
+ WithCopy () {}
+ ~WithCopy () {}
+ WithCopy *Copy (void) const {return new WithCopy ();}
+};
+
+class B
+{
+public:
+ B () {}
+ ~B () {}
+};
+
+class Base
+{
+public:
+ Base () {}
+ virtual ~Base () {}
+};
+
+class DerivedA
+{
+public:
+ DerivedA () {}
+ virtual ~DerivedA () {}
+};
+
+class DerivedB
+{
+public:
+ DerivedB () {}
+ virtual ~DerivedB () {}
+};
+
+
+class ObjectContainerTest : public Test
+{
+public:
+ ObjectContainerTest ();
+ virtual ~ObjectContainerTest ();
+
+ virtual bool RunTests (void);
+};
+
+ObjectContainerTest::ObjectContainerTest ()
+ : Test ("ObjectContainer")
+{}
+
+ObjectContainerTest::~ObjectContainerTest ()
+{}
+
+bool
+ObjectContainerTest::RunTests (void)
+{
+ bool ok = true;
+
+ ObjectContainer container;
+ A *a = new A ();
+ A *firstA = a;
+ container.Acquire (a);
+ a = new A ();
+ container.Acquire (a);
+ a = new A ();
+ container.Acquire (a);
+ B *b = new B ();
+ container.Acquire (b);
+ a = new A ();
+ container.Acquire (a);
+ b = new B ();
+ container.Acquire (b);
+
+ container.Remove (firstA);
+ delete firstA;
+
+ Base *base = new Base ();
+ container.Acquire (base);
+ DerivedA *derivedA = new DerivedA ();
+ container.Acquire (derivedA);
+ DerivedB *derivedB = new DerivedB ();
+ container.Acquire (derivedB);
+ base = new Base ();
+ container.Acquire (base);
+ derivedB = new DerivedB ();
+ container.Acquire (derivedB);
+
+
+ // the following cannot work because no copy method defined.
+ //container.Add (A ());
+ container.Add (WithCopy ());
+
+ container.Cleanup ();
+
+ return ok;
+}
+
+static ObjectContainerTest g_objectContainerTest;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-container.h Mon Mar 19 07:02:14 2007 -0700
@@ -0,0 +1,165 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * 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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef OBJECT_CONTAINER_H
+#define OBJECT_CONTAINER_H
+
+#include <list>
+#include <vector>
+#include <stdint.h>
+#include "fatal-error.h"
+
+namespace ns3 {
+
+
+class ObjectContainer
+{
+public:
+ ~ObjectContainer ();
+ void Cleanup (void);
+
+ template <typename T>
+ void Acquire (T *object);
+
+ template <typename T>
+ T *Add (T const &object);
+
+ template <typename T>
+ void Remove (T *object);
+
+private:
+ typedef void (*ObjectDeleter) (void *);
+ typedef std::list<std::pair<uint32_t,std::vector<void *> *> > List;
+ typedef std::list<std::pair<uint32_t,ObjectDeleter> > DeleterList;
+ template <typename T>
+ static void DeleteObject (void *ptr);
+ template <typename T>
+ uint32_t GetUid (void) const;
+
+ template <typename T>
+ std::vector<T *> *GetVector (void) const;
+
+ uint32_t GetGlobalUid (void) const;
+ uint32_t RegisterUid (uint32_t uid, ObjectDeleter deleter) const;
+ ObjectContainer::ObjectDeleter LookupObjectDeleter (uint32_t uid) const;
+ List m_list;
+ static DeleterList m_deleterList;
+};
+
+}; // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void
+ObjectContainer::Acquire (T *object)
+{
+ uint32_t uid = GetUid<T> ();
+ for (List::iterator i = m_list.begin (); i != m_list.end (); i++)
+ {
+ if (i->first == uid)
+ {
+ i->second->push_back (object);
+ return;
+ }
+ }
+ std::vector<void *> * vec = new std::vector<void *> ();
+ vec->push_back (object);
+ m_list.push_back (std::make_pair (uid, vec));
+}
+
+template <typename T>
+T *
+ObjectContainer::Add (T const &object)
+{
+ T *copy = object.Copy ();
+ Acquire (copy);
+ return copy;
+}
+
+
+template <typename T>
+void
+ObjectContainer::Remove (T *object)
+{
+ uint32_t uid = GetUid<T> ();
+ for (List::iterator i = m_list.begin (); i != m_list.end (); i++)
+ {
+ if (i->first == uid)
+ {
+ for (std::vector<void *>::iterator j = i->second->begin ();
+ j != i->second->end (); j++)
+ {
+ if ((*j) == object)
+ {
+ i->second->erase (j);
+ return;
+ }
+ }
+ goto error;
+ }
+ }
+ error:
+ NS_FATAL_ERROR ("tried to remove non-existant object from object container");
+}
+
+template <typename T>
+std::vector<T *> *
+ObjectContainer::GetVector (void) const
+{
+ uint32_t uid = GetUid<T> ();
+ for (List::const_iterator i = m_list.begin (); i != m_list.end (); i++)
+ {
+ if (i->first == uid)
+ {
+ std::vector<void *> *vec = i->second;
+ std::vector<T *> *retval = (std::vector<T *> *)vec;
+ return retval;
+ }
+ }
+ NS_FATAL_ERROR ("no object registered for requested type.");
+ // quiet compiler
+ return 0;
+}
+
+
+
+
+template <typename T>
+void
+ObjectContainer::DeleteObject (void *ptr)
+{
+ T *object = (T*) ptr;
+ delete object;
+}
+
+template <typename T>
+uint32_t
+ObjectContainer::GetUid (void) const
+{
+ static uint32_t uid = RegisterUid (GetGlobalUid (),
+ &ObjectContainer::DeleteObject<T>);
+ return uid;
+}
+
+}//namespace ns3
+
+
+#endif /* OBJECT_CONTAINER_H */
--- a/src/devices/serial/serial-net-device.cc Mon Mar 19 00:40:44 2007 -0700
+++ b/src/devices/serial/serial-net-device.cc Mon Mar 19 07:02:14 2007 -0700
@@ -83,6 +83,9 @@
resolver->Add ("queue",
MakeCallback (&Queue::CreateTraceResolver, m_queue),
SerialNetDevice::QUEUE);
+ resolver->Add ("rx",
+ m_rxTrace,
+ SerialNetDevice::RX);
return resolver;
}
@@ -119,6 +122,7 @@
// ignore return value for now.
NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
+ m_rxTrace (p);
ForwardUp (p);
}
--- a/src/devices/serial/serial-net-device.h Mon Mar 19 00:40:44 2007 -0700
+++ b/src/devices/serial/serial-net-device.h Mon Mar 19 07:02:14 2007 -0700
@@ -27,6 +27,7 @@
#include "ns3/net-device.h"
#include "ns3/callback.h"
#include "ns3/packet.h"
+#include "ns3/callback-trace-source.h"
namespace ns3 {
@@ -38,6 +39,7 @@
public:
enum TraceType {
QUEUE,
+ RX,
};
SerialNetDevice(Node* node);
virtual ~SerialNetDevice();
@@ -65,7 +67,7 @@
SerialPhy* m_phy;
SerialChannel* m_channel;
Queue* m_queue;
-
+ CallbackTraceSource<Packet &> m_rxTrace;
};
}; // namespace ns3
--- a/src/devices/serial/serial-topology.cc Mon Mar 19 00:40:44 2007 -0700
+++ b/src/devices/serial/serial-topology.cc Mon Mar 19 07:02:14 2007 -0700
@@ -23,6 +23,7 @@
// George F. Riley, Georgia Tech, Spring 2007
#include "ns3/debug.h"
+#include "ns3/assert.h"
#include "ns3/nstime.h"
@@ -54,7 +55,7 @@
// Duplex link is assumed to be subnetted as a /30
// May run this unnumbered in the future?
Ipv4Mask netmask("255.255.255.252");
- assert(netmask.IsMatch(addra,addrb));
+ NS_ASSERT (netmask.IsMatch(addra,addrb));
DropTailQueue* dtqa = new DropTailQueue();