# HG changeset patch # User Tom Henderson # Date 1174312934 25200 # Node ID 8fb57ba7b707f899455a3b37389248a0862b68b0 # Parent 3589721585e73a328962c4ff451bc8968f861b7e Add Mathieu's super object container; add Rx trace on SerialNetDevice diff -r 3589721585e7 -r 8fb57ba7b707 SConstruct --- 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): diff -r 3589721585e7 -r 8fb57ba7b707 samples/ns-2/simple.cc --- 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 +#include #include #include @@ -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 (); } diff -r 3589721585e7 -r 8fb57ba7b707 src/core/object-container.cc --- /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 + */ +#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 *vec = i->second; + ObjectDeleter deleter = LookupObjectDeleter (uid); + for (std::vector::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 */ diff -r 3589721585e7 -r 8fb57ba7b707 src/core/object-container.h --- /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 + */ +#ifndef OBJECT_CONTAINER_H +#define OBJECT_CONTAINER_H + +#include +#include +#include +#include "fatal-error.h" + +namespace ns3 { + + +class ObjectContainer +{ +public: + ~ObjectContainer (); + void Cleanup (void); + + template + void Acquire (T *object); + + template + T *Add (T const &object); + + template + void Remove (T *object); + +private: + typedef void (*ObjectDeleter) (void *); + typedef std::list *> > List; + typedef std::list > DeleterList; + template + static void DeleteObject (void *ptr); + template + uint32_t GetUid (void) const; + + template + std::vector *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 +void +ObjectContainer::Acquire (T *object) +{ + uint32_t uid = GetUid (); + for (List::iterator i = m_list.begin (); i != m_list.end (); i++) + { + if (i->first == uid) + { + i->second->push_back (object); + return; + } + } + std::vector * vec = new std::vector (); + vec->push_back (object); + m_list.push_back (std::make_pair (uid, vec)); +} + +template +T * +ObjectContainer::Add (T const &object) +{ + T *copy = object.Copy (); + Acquire (copy); + return copy; +} + + +template +void +ObjectContainer::Remove (T *object) +{ + uint32_t uid = GetUid (); + for (List::iterator i = m_list.begin (); i != m_list.end (); i++) + { + if (i->first == uid) + { + for (std::vector::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 +std::vector * +ObjectContainer::GetVector (void) const +{ + uint32_t uid = GetUid (); + for (List::const_iterator i = m_list.begin (); i != m_list.end (); i++) + { + if (i->first == uid) + { + std::vector *vec = i->second; + std::vector *retval = (std::vector *)vec; + return retval; + } + } + NS_FATAL_ERROR ("no object registered for requested type."); + // quiet compiler + return 0; +} + + + + +template +void +ObjectContainer::DeleteObject (void *ptr) +{ + T *object = (T*) ptr; + delete object; +} + +template +uint32_t +ObjectContainer::GetUid (void) const +{ + static uint32_t uid = RegisterUid (GetGlobalUid (), + &ObjectContainer::DeleteObject); + return uid; +} + +}//namespace ns3 + + +#endif /* OBJECT_CONTAINER_H */ diff -r 3589721585e7 -r 8fb57ba7b707 src/devices/serial/serial-net-device.cc --- 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); } diff -r 3589721585e7 -r 8fb57ba7b707 src/devices/serial/serial-net-device.h --- 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 m_rxTrace; }; }; // namespace ns3 diff -r 3589721585e7 -r 8fb57ba7b707 src/devices/serial/serial-topology.cc --- 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();