Add Mathieu's super object container; add Rx trace on SerialNetDevice

This commit is contained in:
Tom Henderson
2007-03-19 07:02:14 -07:00
parent cd132b39ed
commit d156b4ab86
7 changed files with 473 additions and 126 deletions

View File

@@ -24,6 +24,7 @@ core.add_sources([
'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 @@ core.add_inst_headers([
'fatal-error.h',
'test.h',
'random-variable.h',
'rng-stream.h'
'rng-stream.h',
'object-container.h'
])
def config_core (env, config):

View File

@@ -37,6 +37,7 @@
// - Tracing of queues and packet receptions to file "out.tr"
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
@@ -63,110 +64,86 @@
#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 () {};
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;
}
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;
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;
};
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
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
GenerateTraffic (DatagramSocket *socket, uint32_t size)
@@ -230,6 +207,8 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
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 @@ int main (int argc, char *argv[])
// 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 ();
}

View File

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

165
src/core/object-container.h Normal file
View File

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

View File

@@ -83,6 +83,9 @@ SerialNetDevice::DoCreateTraceResolver (TraceContext const &context)
resolver->Add ("queue",
MakeCallback (&Queue::CreateTraceResolver, m_queue),
SerialNetDevice::QUEUE);
resolver->Add ("rx",
m_rxTrace,
SerialNetDevice::RX);
return resolver;
}
@@ -119,6 +122,7 @@ SerialNetDevice::Receive (Packet& p)
// ignore return value for now.
NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
m_rxTrace (p);
ForwardUp (p);
}

View File

@@ -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 @@ class SerialNetDevice : public NetDevice {
public:
enum TraceType {
QUEUE,
RX,
};
SerialNetDevice(Node* node);
virtual ~SerialNetDevice();
@@ -65,7 +67,7 @@ private:
SerialPhy* m_phy;
SerialChannel* m_channel;
Queue* m_queue;
CallbackTraceSource<Packet &> m_rxTrace;
};
}; // namespace ns3

View File

@@ -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 @@ SerialTopology::AddSerialLink(
// 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();