move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu
authorTom Henderson <tomh@tomh.org>
Sun, 18 Mar 2007 14:06:51 -0700
changeset 345 47b41507a45a
parent 344 b547ec7dbbc1
child 348 1802fde7996c
move channel.cc channel.h to node directory; merge ns-3-tracing from mathieu
SConstruct
samples/main-serial-net-device-if.cc
samples/main-trace.cc
samples/ns-2/simple.cc
src/common/array-trace-resolver.h
src/common/callback-trace-source.cc
src/common/callback-trace-source.h
src/common/callback-tracer.h
src/common/composite-trace-resolver.cc
src/common/composite-trace-resolver.h
src/common/empty-trace-resolver.cc
src/common/empty-trace-resolver.h
src/common/f-variable-tracer.h
src/common/fv-trace-source.h
src/common/si-variable-tracer.h
src/common/sv-trace-source.h
src/common/terminal-trace-resolver.h
src/common/trace-container.cc
src/common/trace-container.h
src/common/trace-context.cc
src/common/trace-context.h
src/common/trace-resolver.cc
src/common/trace-resolver.h
src/common/trace-root.cc
src/common/trace-root.h
src/common/ui-variable-tracer.h
src/common/uv-trace-source.h
src/common/variable-tracer-test.cc
src/core/callback-test.cc
src/core/callback.h
src/core/fatal-error.h
src/devices/p2p/p2p-net-device.cc
src/devices/p2p/p2p-net-device.h
src/devices/serial/channel.cc
src/devices/serial/channel.h
src/devices/serial/serial-channel.cc
src/devices/serial/serial-channel.h
src/devices/serial/serial-net-device.cc
src/devices/serial/serial-net-device.h
src/devices/serial/serial-phy.cc
src/devices/serial/serial-phy.h
src/node/arp-ipv4-interface.cc
src/node/arp-ipv4-interface.h
src/node/arp.cc
src/node/arp.h
src/node/channel.cc
src/node/channel.h
src/node/drop-tail.cc
src/node/drop-tail.h
src/node/internet-node.cc
src/node/internet-node.h
src/node/ipv4-interface.cc
src/node/ipv4-interface.h
src/node/ipv4-l4-demux.cc
src/node/ipv4-l4-demux.h
src/node/ipv4-l4-protocol.h
src/node/ipv4-loopback-interface.cc
src/node/ipv4-loopback-interface.h
src/node/ipv4.cc
src/node/ipv4.h
src/node/l3-demux.cc
src/node/l3-demux.h
src/node/l3-protocol.cc
src/node/l3-protocol.h
src/node/net-device.cc
src/node/net-device.h
src/node/node-list.cc
src/node/node-list.h
src/node/node.h
src/node/queue.cc
src/node/queue.h
src/node/udp.cc
src/node/udp.h
src/simulator/simulator.h
--- a/SConstruct	Sun Mar 18 19:31:32 2007 +0100
+++ b/SConstruct	Sun Mar 18 14:06:51 2007 -0700
@@ -140,9 +140,15 @@
     'tags.cc',
     'pcap-writer.cc',
     'trace-writer.cc',
-    'trace-container.cc',
     'variable-tracer-test.cc',
-    'stream-tracer-test.cc',
+    'trace-context.cc',
+    'trace-resolver.cc',
+    'callback-trace-source.cc',
+    'empty-trace-resolver.cc',
+    'composite-trace-resolver.cc',
+    'trace-root.cc',
+    ])
+common.add_headers ([
     ])
 common.add_inst_headers([
     'buffer.h',
@@ -150,14 +156,19 @@
     'trailer.h',
     'tags.h',
     'packet.h',
-    'ui-variable-tracer.h',
-    'si-variable-tracer.h',
-    'f-variable-tracer.h',
-    'callback-tracer.h',
-    'stream-tracer.h',
+    'uv-trace-source.h',
+    'sv-trace-source.h',
+    'fv-trace-source.h',
     'trace-writer.h',
-    'trace-container.h',
     'pcap-writer.h',
+    'callback-trace-source.h',
+    'trace-context.h',
+    'trace-resolver.h',
+    'empty-trace-resolver.h',
+    'composite-trace-resolver.h',
+    'array-trace-resolver.h',
+    'trace-root.h',
+    'terminal-trace-resolver.h',
     ])
 
 node = build.Ns3Module ('node', 'src/node')
@@ -193,6 +204,8 @@
     'net-device-list.cc',
     'queue.cc',
     'drop-tail.cc',
+    'channel.cc',
+    'node-list.cc',
     ])
 node.add_headers ([
     'ipv4-header.h',
@@ -229,10 +242,12 @@
     'arp-header.h',
     'ipv4-header.h',
     'udp-header.h',
+    'channel.h',
+    'node-list.h',
     ])
 
 p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
-ns3.add (p2p)
+#ns3.add (p2p)
 p2p.add_deps (['node'])
 p2p.add_sources ([
     'p2p-net-device.cc',
@@ -251,7 +266,6 @@
     'serial-channel.cc',
     'serial-phy.cc',
     'layer-connector.cc',
-    'channel.cc',
     ])
 serial.add_headers ([
     'propagator.h',
@@ -261,7 +275,6 @@
     'serial-channel.h',
     'serial-phy.h',
     'layer-connector.h',
-    'channel.h',
     ])
 
 
@@ -312,7 +325,7 @@
 sample_ptr.add_source('main-ptr.cc')
 
 sample_trace = build.Ns3Module('sample-trace', 'samples')
-ns3.add(sample_trace)
+#ns3.add(sample_trace)
 sample_trace.add_dep('common')
 sample_trace.set_executable()
 sample_trace.add_source('main-trace.cc')
@@ -349,7 +362,7 @@
 
 sample_sp2p = build.Ns3Module('sample-simple-p2p', 'samples')
 sample_sp2p.set_executable()
-ns3.add(sample_sp2p)
+#n3.add(sample_sp2p)
 sample_sp2p.add_deps(['core', 'simulator', 'node', 'p2p'])
 sample_sp2p.add_source('main-simple-p2p.cc')
 
--- a/samples/main-serial-net-device-if.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/samples/main-serial-net-device-if.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -31,12 +31,15 @@
 #include "ns3/serial-channel.h"
 #include "ns3/serial-net-device.h"
 #include "ns3/trace-writer.h"
-#include "ns3/trace-container.h"
 #include "ns3/drop-tail.h"
 #include "ns3/arp-ipv4-interface.h"
 #include "ns3/ipv4.h"
+#include "ns3/trace-context.h"
+#include "ns3/udp-socket.h"
+#include "ns3/simulator.h"
+#include "ns3/node-list.h"
+#include "ns3/trace-root.h"
 
-#include "ns3/pcap-writer.h"
 
 using namespace ns3;
 
@@ -61,27 +64,74 @@
 
   ~Logger () {}
 
-  void Log (std::string const &name, const Packet &p)
+  void Log (TraceContext const &context, const Packet &p)
   {
-    NS_DEBUG_UNCOND("**** LogEnque ("<< name << " " << &p << ")");
-    m_filestr << name << " " << &p << std::endl;
+    NodeList::NodeIndex nodeIndex;
+    context.Get (nodeIndex);
+    m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+    Ipv4::InterfaceIndex interfaceIndex;
+    context.Get (interfaceIndex);
+    m_filestr << "interface=" << interfaceIndex << " ";
+    enum Queue::TraceType type;
+    context.Get (type);
+    switch (type) 
+      {
+      case Queue::ENQUEUE:
+        m_filestr << "enqueue";
+        break;
+      case Queue::DEQUEUE:
+        m_filestr << "dequeue";
+        break;
+      case Queue::DROP:
+        m_filestr << "drop";
+        break;
+      }
+    m_filestr << " bytes=" << p.GetSize () << std::endl;
   }
 
 protected:
   TraceWriter m_tracer;
 };
 
+static void
+GenerateTraffic (UdpSocket *socket, uint32_t size)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " tx bytes=" << size << std::endl;
+  socket->SendDummy (size);
+  if (size > 50)
+    {
+      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
+    }
+}
+
+static void
+UdpSocketPrinter (UdpSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " rx bytes=" << size << std::endl;
+}
+
+static void
+PrintTraffic (UdpSocket *socket)
+{
+  socket->SetDummyRxCallback (MakeCallback (&UdpSocketPrinter));
+}
+
+
 int main (int argc, char *argv[])
 {
   NS_DEBUG_UNCOND("Serial Net Device Test");
 
-  TraceContainer traceContainerA;
-  TraceContainer traceContainerB;
-  
   // create two nodes and a simple SerialChannel
   InternetNode a;
   InternetNode b;
-  SerialChannel ch;
+  SerialChannel ch = SerialChannel ("Test Channel", 1000, Seconds (0.1));
+
+  NodeList::Add (&a);
+  NodeList::Add (&b);
 
   // create two NetDevices and assign one to each node
   // Note:  this would normally be done also in conjunction with
@@ -94,8 +144,7 @@
   MacAddress addra("00:00:00:00:00:01");
   SerialNetDevice neta(&a, addra);
 
-  DropTailQueue dtqa ("a");
-  dtqa.RegisterTraces (traceContainerA);
+  DropTailQueue dtqa;
 
   neta.AddQueue(&dtqa);
   neta.SetName("a.eth0"); 
@@ -103,16 +152,15 @@
   MacAddress addrb("00:00:00:00:00:02");
   SerialNetDevice netb(&b, addrb);
 
-  DropTailQueue dtqb ("b");
-  dtqb.RegisterTraces (traceContainerB);
+  DropTailQueue dtqb;
 
   netb.AddQueue(&dtqb);
   netb.SetName("b.eth0"); 
 
   // bind the two NetDevices together by using a simple Channel
   // this method changed to do a bidirectional binding
-  ch.Attach(&neta);
-  ch.Attach(&netb);
+  neta.Attach (&ch);
+  netb.Attach (&ch);
 
   // Some simple prints to see whether it is working
   NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
@@ -153,6 +201,9 @@
   NS_DEBUG_UNCOND("Setting ARP interface to UP");
   arpipv4interfacep->SetUp();
 
+  a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
+
+
   NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
   ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
   uint32_t indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
@@ -170,20 +221,28 @@
   NS_DEBUG_UNCOND("Setting ARP interface to UP");
   arpipv4interfacepb->SetUp();
 
+  b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
+
+
+  UdpSocket *source = new UdpSocket (&a);
+  UdpSocket *sink = new UdpSocket(&b);
+  sink->Bind (80);
+  source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
+
   Logger logger("serial-net-test.log");
 
-  traceContainerA.SetCallback ("Queue::Enque", 
-                               MakeCallback (&Logger::Log, &logger));
+  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*", 
+                      MakeCallback (&Logger::Log, &logger));
+
+  PrintTraffic (sink);
+  GenerateTraffic (source, 100);
 
-  // create a packet on one node and send it through, reading it
-  // on the other node
-  Packet p;
+  Simulator::Run ();
 
-  NS_DEBUG_UNCOND("Sending Packet " << &p);
-  arpipv4interfacep->Send(p, Ipv4Address("10.1.1.2"));
+  Simulator::Destroy ();
 
-  //neta.Send(p, MacAddress());  // Test that all-zero's MacAddress used
-  //netb.Send(p, "00:01:02:03:04:05");  // Dummy function call
+  delete source;
+  delete sink;
 
   return 0;
 }
--- a/samples/main-trace.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/samples/main-trace.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -9,10 +9,10 @@
 
 using namespace ns3;
 
-CallbackTracer<Packet> a;
+CallbackTraceSourcer<Packet> a;
 UiVariableTracer<unsigned short> b;
 StreamTracer c;
-CallbackTracer<double, int> d;
+CallbackTraceSourcer<double, int> d;
 
 void
 RegisterAllTraceSources (TraceContainer *container)
--- a/samples/ns-2/simple.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/samples/ns-2/simple.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -48,6 +48,7 @@
 
 #include "ns3/internet-node.h"
 #include "ns3/serial-channel.h"
+#include "ns3/serial-net-device.h"
 #include "ns3/mac-address.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/arp-ipv4-interface.h"
@@ -60,6 +61,8 @@
 #include "ns3/arp-header.h"
 #include "ns3/ipv4-header.h"
 #include "ns3/udp-header.h"
+#include "ns3/node-list.h"
+#include "ns3/trace-root.h"
 
 using namespace ns3;
 
@@ -81,23 +84,37 @@
 
   ~Tracer () {};
 
-  void LogEnqueue (std::string const &name, const Packet &p)
+  void LogNodeInterface (TraceContext const &context)
   {
-    m_filestr << name << " que ";
-    PrintLlcPacket (p, m_filestr);
+    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)
+  {
+    LogNodeInterface (context);
+    m_filestr << " que p=" << p.GetUid ();
+    //PrintLlcPacket (p, m_filestr);
     m_filestr << std::endl;
   }
 
-  void LogDequeue (std::string const &name, const Packet &p)
+  void LogDequeue (TraceContext const &context, const Packet &p)
   {
-    m_filestr << name << " deq ";
-    PrintLlcPacket (p, m_filestr);
+    LogNodeInterface (context);
+    m_filestr << " deq p=" << p.GetUid ();
+    //PrintLlcPacket (p, m_filestr);
     m_filestr << std::endl;
   }
-  void LogDrop (std::string const &name, const Packet &p)
+  void LogDrop (TraceContext const &context, const Packet &p)
   {
-    m_filestr << name << " dro ";
-    PrintLlcPacket (p, m_filestr);
+    LogNodeInterface (context);
+    m_filestr << " dro p=" << p.GetUid ();
+    //PrintLlcPacket (p, m_filestr);
     m_filestr << std::endl;
   }
 
@@ -199,7 +216,7 @@
 
 static SerialChannel * 
 AddDuplexLink(
-  std::string &name,
+  std::string name,
   uint64_t bps,
   uint32_t delay,
   InternetNode* a, 
@@ -207,12 +224,8 @@
   const MacAddress& macaddra, 
   InternetNode* b, 
   const Ipv4Address& addrb,
-  const MacAddress& macaddrb, 
-  // const Rate& rate, 
-  // const Time& delay,
-  TraceContainer &traceContainer)
+  const MacAddress& macaddrb)
 {
-  std::string qName;
   SerialChannel* channel = new SerialChannel(name, bps, MilliSeconds(delay));
 
   // Duplex link is assumed to be subnetted as a /30
@@ -220,30 +233,24 @@
   Ipv4Mask netmask("255.255.255.252");
   assert(netmask.IsMatch(addra,addrb));
 
-  qName = name + "::Queue A";
-  DropTailQueue* dtqa = new DropTailQueue(qName);
-  dtqa->RegisterTraces (traceContainer);
+  DropTailQueue* dtqa = new DropTailQueue();
 
   SerialNetDevice* neta = new SerialNetDevice(a, macaddra);
   neta->AddQueue(dtqa);
   Ipv4Interface *interfA = new ArpIpv4Interface (a, neta);
   uint32_t indexA = a->GetIpv4 ()->AddInterface (interfA);
-  channel->Attach (neta);
   neta->Attach (channel);
   
   interfA->SetAddress (addra);
   interfA->SetNetworkMask (netmask);
   interfA->SetUp ();
 
-  qName = name + "::Queue B";
-  DropTailQueue* dtqb = new DropTailQueue(qName);
-  dtqb->RegisterTraces (traceContainer);
+  DropTailQueue* dtqb = new DropTailQueue();
 
   SerialNetDevice* netb = new SerialNetDevice(b, macaddrb);
   netb->AddQueue(dtqb);
   Ipv4Interface *interfB = new ArpIpv4Interface (b, netb);
   uint32_t indexB = b->GetIpv4 ()->AddInterface (interfB);
-  channel->Attach (netb);
   netb->Attach (channel);
 
   interfB->SetAddress (addrb);
@@ -262,19 +269,6 @@
   return channel;
 }
 
-static void
-SetupTrace (TraceContainer &container, Tracer &tracer)
-{
-  container.SetCallback ("Queue::Enqueue",
-                         MakeCallback (&Tracer::LogEnqueue, &tracer));
-  
-  container.SetCallback ("Queue::Dequeue",
-                         MakeCallback (&Tracer::LogDequeue, &tracer));
-  
-  container.SetCallback ("Queue::Drop",
-                         MakeCallback (&Tracer::LogDrop, &tracer));
-
-}
 
 int main (int argc, char *argv[])
 {
@@ -295,37 +289,27 @@
   InternetNode *n2 = new InternetNode();
   InternetNode *n3 = new InternetNode();
 
-  TraceContainer traceContainer;
+  NodeList::Add (n0);
+  NodeList::Add (n1);
+  NodeList::Add (n2);
+  NodeList::Add (n3);
 
   n0->SetName(std::string("Node 0"));
   n1->SetName(std::string("Node 1"));
   n2->SetName(std::string("Node 2"));
   n3->SetName(std::string("Node 3"));
   
-  Tracer tracer("serial-net-test.log");
-    
-  std::string channelName;
-    
-  channelName = "Channel 1";
-  SerialChannel* ch1 = AddDuplexLink (channelName, 5000000, 2,
+  SerialChannel* ch1 = AddDuplexLink ("Channel 1", 5000000, 2,
       n0, Ipv4Address("10.1.1.1"), MacAddress("00:00:00:00:00:01"), 
-      n2, Ipv4Address("10.1.1.2"), MacAddress("00:00:00:00:00:02"), 
-      traceContainer);
-  SetupTrace (traceContainer, tracer);
+      n2, Ipv4Address("10.1.1.2"), MacAddress("00:00:00:00:00:02"));
+  
+  SerialChannel* ch2 = AddDuplexLink ("Channel 2", 5000000, 2,
+      n1, Ipv4Address("10.1.2.1"), MacAddress("00:00:00:00:00:03"), 
+      n2, Ipv4Address("10.1.2.2"), MacAddress("00:00:00:00:00:04"));
 
-  channelName = "Channel 2";
-  SerialChannel* ch2 = AddDuplexLink (channelName, 5000000, 2,
-      n1, Ipv4Address("10.1.2.1"), MacAddress("00:00:00:00:00:03"), 
-      n2, Ipv4Address("10.1.2.2"), MacAddress("00:00:00:00:00:04"), 
-      traceContainer);
-  SetupTrace (traceContainer, tracer);
-
-  channelName = "Channel 3";
-  SerialChannel* ch3 = AddDuplexLink (channelName, 1500000, 10,
+  SerialChannel* ch3 = AddDuplexLink ("Channel 3", 1500000, 10,
       n2, Ipv4Address("10.1.3.1"), MacAddress("00:00:00:00:00:05"), 
-      n3, Ipv4Address("10.1.3.2"), MacAddress("00:00:00:00:00:06"), 
-      traceContainer);
-  SetupTrace (traceContainer, tracer);
+      n3, Ipv4Address("10.1.3.2"), MacAddress("00:00:00:00:00:06"));
   
   UdpSocket *source0 = new UdpSocket (n0);
   UdpSocket *source3 = new UdpSocket (n3);
@@ -341,6 +325,15 @@
   n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
   n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
 
+  Tracer tracer("serial-net-test.log");
+  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));
+
+
   PrintTraffic (sink3);
   GenerateTraffic (source0, 100);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/array-trace-resolver.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,138 @@
+/* -*- 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 ARRAY_TRACE_RESOLVER_H
+#define ARRAY_TRACE_RESOLVER_H
+
+#include <stdint.h>
+#include <string>
+#include "ns3/callback.h"
+#include "trace-resolver.h"
+
+namespace ns3 {
+
+/**
+ * \brief a helper class to offer trace resolution for an array of objects.
+ * \ingroup tracing
+ */
+template <typename T>
+class ArrayTraceResolver : public TraceResolver
+{
+public:
+  /**
+   * \brief array index trace context
+   *
+   * During namespace parsing, ns3::ArrayTraceResolver will
+   * embed an instance of this class in the TraceContext 
+   * associated to every child object of the object stored
+   * at the index.
+   *
+   * The reason why this class exists is to ensure that we 
+   * need to ensure that we can store a unique type as context 
+   * into the TraceContext associated to this trace resolver.
+   */
+  class Index
+  {
+  public:
+    Index ();
+    Index (uint32_t index);
+    /**
+     * The Index is automatically convertible to the 
+     * uin32_t type such that it really behaves like a uint32_t
+     * array index for the user. 
+     *
+     * \returns the index itself
+     */
+    operator uint32_t ();
+  private:
+    uint32_t m_index;
+  };
+  /**
+   * \param context trace context associated to this trace resolver
+   * \param getSize callback which returns dynamically the size of underlying array
+   * \param get callback which returns any element in the underlying array
+   *
+   * Construct a trace resolver which can match any input integer
+   * against an element in an array. The array is accessed using a 
+   * pair of callbacks. It is the responsability of the user to
+   * provide two such callbacks whose job is to adapt the array
+   * API to the resolver needs. Each element of the array is expected
+   * to provide a method named CreateTraceResolver which takes as
+   * only argument a reference to a const TraceContext and returns
+   * a pointer to a TraceResolver. i.e. the signature is:
+   * TraceResolver * (*) (TraceContext const &)
+   */
+  ArrayTraceResolver (TraceContext const &context,
+                      Callback<uint32_t> getSize, 
+                      Callback<T *, uint32_t> get);
+private:
+  virtual TraceResolverList DoLookup (std::string id) const;
+  Callback<uint32_t> m_getSize;
+  Callback<T *, uint32_t> m_get;
+};
+
+}//namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+ArrayTraceResolver<T>::Index::Index ()
+  : m_index ()
+{}
+template <typename T>
+ArrayTraceResolver<T>::Index::Index (uint32_t index)
+  : m_index (index)
+{}
+template <typename T>
+ArrayTraceResolver<T>::Index::operator uint32_t ()
+{
+  return m_index;
+}
+
+template <typename T>
+ArrayTraceResolver<T>::ArrayTraceResolver (TraceContext const &context,
+                                                   Callback<uint32_t> getSize, 
+						   Callback<T *, uint32_t> get)
+  : TraceResolver (context),
+    m_getSize (getSize),
+    m_get (get)
+{}
+template <typename T>
+TraceResolver::TraceResolverList 
+ArrayTraceResolver<T>::DoLookup (std::string id) const
+{
+  TraceResolverList list;
+  if (id == "*")
+    {
+      for (uint32_t i = 0; i < m_getSize (); i++)
+	{
+	  TraceContext context = GetContext ();
+          typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
+	  context.Add (index);
+	  list.push_back (m_get (i)->CreateTraceResolver (context));
+	}
+    }
+  return list;
+}
+
+
+}//namespace ns3
+
+#endif /* ARRAY_TRACE_RESOLVER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/callback-trace-source.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,95 @@
+/* -*- 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 "callback-trace-source.h"
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class CallbackTraceSourceTest : public Test 
+{
+public:
+  CallbackTraceSourceTest ();
+  virtual ~CallbackTraceSourceTest ();
+  virtual bool RunTests (void);
+private:
+  void CbOne (TraceContext const &context, uint8_t a, double b);
+  void CbTwo (TraceContext const &context, uint8_t a, double b);
+
+  bool m_one;
+  bool m_two;
+};
+
+CallbackTraceSourceTest::CallbackTraceSourceTest ()
+  : Test ("CallbackTraceSource")
+{}
+CallbackTraceSourceTest::~CallbackTraceSourceTest ()
+{}
+void
+CallbackTraceSourceTest::CbOne (TraceContext const &context, uint8_t a, double b)
+{
+  m_one = true;
+}
+void
+CallbackTraceSourceTest::CbTwo (TraceContext const &context, uint8_t a, double b)
+{
+  m_two = true;
+}
+bool 
+CallbackTraceSourceTest::RunTests (void)
+{
+  bool ok = true;
+  TraceContext ctx;
+
+  CallbackTraceSource<uint8_t,double> trace;
+  trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this), ctx);
+  trace.AddCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this), ctx);
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  if (!m_one || !m_two)
+    {
+      ok = false;
+    }
+  trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbOne, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  if (m_one || !m_two)
+    {
+      ok = false;
+    }
+  trace.RemoveCallback (MakeCallback (&CallbackTraceSourceTest::CbTwo, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  if (m_one || m_two)
+    {
+      ok = false;
+    }
+
+  return ok;
+}
+
+CallbackTraceSourceTest g_callbackTraceTest;
+
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/callback-trace-source.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,163 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,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 CALLBACK_TRACE_H
+#define CALLBACK_TRACE_H
+
+#include <list>
+#include "ns3/callback.h"
+#include "ns3/fatal-error.h"
+#include "trace-context.h"
+
+namespace ns3 {
+
+
+/**
+ * \brief log arbitrary number of parameters to a matching ns3::Callback
+ * \ingroup tracing
+ *
+ * Whenever operator () is invoked on this class, the call and its arguments
+ * are forwarded to the internal matching ns3::Callback.
+ */
+template<typename T1 = empty, typename T2 = empty, 
+         typename T3 = empty, typename T4 = empty>
+class CallbackTraceSource {
+public:
+  CallbackTraceSource ();
+  void AddCallback (CallbackBase const & callback, TraceContext const & context);
+  void RemoveCallback (CallbackBase const & callback);
+  void operator() (void);
+  void operator() (T1 a1);
+  void operator() (T1 a1, T2 a2);
+  void operator() (T1 a1, T2 a2, T3 a3);
+  void operator() (T1 a1, T2 a2, T3 a3, T4 a4);
+
+private:
+  typedef std::list<Callback<void,TraceContext const &,T1,T2,T3,T4> > CallbackList;
+  TraceContext m_context;
+  CallbackList m_callbackList;
+};
+
+}; // namespace ns3
+
+// implementation below.
+
+namespace ns3 {
+
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+CallbackTraceSource<T1,T2,T3,T4>::CallbackTraceSource ()
+  : m_callbackList () 
+{}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::AddCallback (CallbackBase const & callback,
+                                               TraceContext const &context)
+{
+  Callback<void,TraceContext const &,T1,T2,T3,T4> cb;
+  if (!cb.CheckType (callback))
+    {
+      NS_FATAL_ERROR ("Incompatible callbacks. (feed to \"c++filt -t\"): got=\"" << 
+		      typeid (callback).name () << "\" expected=\"" <<
+		      typeid (cb).name () << "\"");
+    }
+  m_context.Add (context);
+  cb = *static_cast<Callback<void,TraceContext const &,T1,T2,T3,T4> const *> (&callback);
+  m_callbackList.push_back (cb);
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::RemoveCallback (CallbackBase const & callback)
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); /* empty */)
+    {
+      if ((*i).IsEqual (callback))
+	{
+	  i = m_callbackList.erase (i);
+	}
+      else
+	{
+	  i++;
+	}
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::operator() (void) 
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (m_context);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1) 
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (m_context, a1);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2) 
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (m_context, a1, a2);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3) 
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (m_context, a1, a2, a3);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+CallbackTraceSource<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4) 
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (m_context, a1, a2, a3, a4);
+    }
+}
+
+}//namespace ns3
+
+#endif /* CALLBACK_TRACE_H */
--- a/src/common/callback-tracer.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006 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 CALLBACK_TRACER_H
-#define CALLBACK_TRACER_H
-
-#include "ns3/callback.h"
-
-namespace ns3 {
-
-class CallbackTracerBase {
-public:
-  virtual ~CallbackTracerBase () {}
-  bool CheckCallbackType (CallbackBase const&callback)
-  {
-    return CheckType (callback);
-  }
-private:
-  virtual bool CheckType (CallbackBase const&callback) = 0;
-};
-
-
-/**
- * \brief log arbitrary number of parameters to a matching ns3::Callback
- *
- * Whenever operator () is invoked on this class, the call and its arguments
- * are forwarded to the internal matching ns3::Callback.
- */
-template<typename T1 = empty, typename T2 = empty, 
-         typename T3 = empty, typename T4 = empty,
-         typename T5 = empty>
-class CallbackTracer : public CallbackTracerBase {
-public:
-  CallbackTracer ()
-      : m_callback () {}
-  void SetCallback (Callback<void,T1,T2,T3,T4,T5> callback)
-  {
-    m_callback = callback;
-  }
-  void operator() (void) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback ();
-        }
-  }
-  void operator() (T1 a1) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback (a1);
-        }
-  }
-  void operator() (T1 a1, T2 a2) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback (a1,a2);
-        }
-  }
-  void operator() (T1 a1, T2 a2, T3 a3) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback (a1,a2,a3);
-        }
-  }
-  void operator() (T1 a1, T2 a2, T3 a3, T4 a4) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback (a1,a2,a3,a4);
-        }
-  }
-  void operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) 
-  {
-      if (!m_callback.IsNull ()) 
-        {
-          m_callback (a1,a2,a3,a4,a5);
-        }
-  }
-
-private:
-  virtual bool CheckType (CallbackBase const&callback)
-  {
-    return m_callback.CheckType (callback);
-  }
-  Callback<void,T1,T2,T3,T4,T5> m_callback;
-};
-
-}; // namespace ns3
-
-#endif /* CALLBACK_TRACER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/composite-trace-resolver.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,331 @@
+/* -*- 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 "composite-trace-resolver.h"
+
+namespace ns3 {
+
+CompositeTraceResolver::CompositeTraceResolver (TraceContext const &context)
+  : TraceResolver (context)
+{}
+
+CompositeTraceResolver::~CompositeTraceResolver ()
+{}
+
+void 
+CompositeTraceResolver::DoAdd (std::string name, 
+			       Callback<TraceResolver *,TraceContext const &> createResolver,
+			       TraceContext const &context)
+{
+  struct CallbackTraceSourceItem item;
+  item.name = name;
+  item.createResolver = createResolver;
+  item.context = context;
+  m_items.push_back (item);
+}
+
+TraceResolver::TraceResolverList 
+CompositeTraceResolver::DoLookup (std::string id) const
+{
+  if (id == "*")
+    {
+      TraceResolver::TraceResolverList list;
+      for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
+	{
+	  list.push_back (i->createResolver (i->context));
+	}
+      return list;
+    }
+  std::string::size_type start, end;
+  start = id.find_first_of ("(", 0);
+  end = id.find_first_of (")", 0);
+  if (start != 0 || end != (id.size ()-1))
+    {
+      for (TraceItems::const_iterator i = m_items.begin (); i != m_items.end (); i++)
+	{
+	  if (i->name == id)
+	    {
+	      TraceResolver::TraceResolverList list;
+	      list.push_back (i->createResolver (i->context));
+	      return list;
+	    }
+	}
+    }
+  std::list<std::string> names;
+  std::string alternatives = std::string (id, start+1, end-1);
+  std::string::size_type next, cur;
+  next = 0;
+  cur = 0;
+  while (true)
+    {
+      std::string element;
+      next = alternatives.find ("|", cur);
+      if (next == std::string::npos)
+	{
+	  element = std::string (alternatives, cur, alternatives.size ());
+	  names.push_back (element);
+	  break;
+	}
+      element = std::string (alternatives, cur, next);
+      names.push_back (element);
+      cur = next + 1;
+    }
+  TraceResolver::TraceResolverList list;
+  for (std::list<std::string>::const_iterator i = names.begin (); i != names.end (); i++)
+    {
+      for (TraceItems::const_iterator j = m_items.begin (); j != m_items.end (); j++)
+	{
+	  if (j->name == *i)
+	    {
+	      list.push_back (j->createResolver (j->context));
+	      break;
+	    }
+	}
+    }
+  return list;
+}
+
+}//namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class CompositeTraceResolverTest : public Test
+{
+public:
+  enum TraceSources {
+    TEST_TRACE_DOUBLEA,
+    TEST_TRACE_DOUBLEB,
+    TEST_TRACE_SUBRESOLVER,
+  };
+  enum SubTraceSources {
+    TEST_SUBTRACE_INT,
+  };
+  CompositeTraceResolverTest ();
+  virtual ~CompositeTraceResolverTest ();
+  virtual bool RunTests (void);
+private:
+  void TraceDouble (TraceContext const &context, double v);
+  void TraceInt (TraceContext const &context, int v);
+  TraceResolver *CreateSubResolver (TraceContext const &context);
+
+
+  bool m_gotDoubleA;
+  bool m_gotDoubleB;
+  CallbackTraceSource<int> m_traceInt;
+  bool m_gotInt;
+};
+
+CompositeTraceResolverTest::CompositeTraceResolverTest ()
+  : Test ("CompositeTraceResolver")
+{}
+CompositeTraceResolverTest::~CompositeTraceResolverTest ()
+{}
+void 
+CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
+{
+  enum CompositeTraceResolverTest::TraceSources source;
+  context.Get (source);
+  switch (source)
+    {
+    case TEST_TRACE_DOUBLEA:
+      m_gotDoubleA = true;
+      break;
+    case TEST_TRACE_DOUBLEB:
+      m_gotDoubleB = true;
+      break;
+    default:
+      NS_FATAL_ERROR ("should not get any other trace source in this sink");
+      break;
+    }
+  
+}
+
+void 
+CompositeTraceResolverTest::TraceInt (TraceContext const &context, int v)
+{
+  m_gotInt = true;
+}
+
+TraceResolver *
+CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *subresolver = new CompositeTraceResolver (context);
+  subresolver->Add ("trace-int", m_traceInt, TEST_SUBTRACE_INT);
+  return subresolver;
+}
+bool 
+CompositeTraceResolverTest::RunTests (void)
+{
+  bool ok = true;
+
+  CallbackTraceSource<double> traceDoubleA;
+  CallbackTraceSource<double> traceDoubleB;
+  TraceContext context;
+
+  CompositeTraceResolver resolver (context) ;
+
+  resolver.Add ("trace-double-a", traceDoubleA, TEST_TRACE_DOUBLEA);
+  resolver.Add ("trace-double-b", traceDoubleB, TEST_TRACE_DOUBLEB);
+
+  resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  if (!m_gotDoubleA || m_gotDoubleB)
+    {
+      ok = false;
+    }
+  m_gotDoubleA = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (!m_gotDoubleA || !m_gotDoubleB)
+    {
+      ok = false;
+    }
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+
+  resolver.Disconnect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (m_gotDoubleA || m_gotDoubleB)
+    {
+      ok = false;
+    }
+
+  resolver.Connect ("/trace-double-a", 
+		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (!m_gotDoubleA || m_gotDoubleB)
+    {
+      ok = false;
+    }
+  resolver.Disconnect ("/trace-double-a", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+
+  resolver.Connect ("/(trace-double-a)", 
+		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (!m_gotDoubleA || m_gotDoubleB)
+    {
+      ok = false;
+    }
+  resolver.Disconnect ("/trace-double-a", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+
+  resolver.Connect ("/(trace-double-a|trace-double-b)", 
+		    MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (!m_gotDoubleA || !m_gotDoubleB)
+    {
+      ok = false;
+    }
+  resolver.Disconnect ("/trace-double-a", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (m_gotDoubleA || !m_gotDoubleB)
+    {
+      ok = false;
+    }
+
+
+  resolver.Disconnect ("/(trace-double-a|trace-double-b)", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
+  m_gotDoubleA = false;
+  m_gotDoubleB = false;
+  traceDoubleA (0);
+  traceDoubleB (0);
+  if (m_gotDoubleA || m_gotDoubleB)
+    {
+      ok = false;
+    }
+
+  resolver.Add ("subresolver", 
+		MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this),
+		TEST_TRACE_SUBRESOLVER);
+
+  resolver.Connect ("/subresolver/trace-int", 
+		    MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
+  m_gotInt = false;
+  m_traceInt (1);
+  if (!m_gotInt)
+    {
+      ok = false;
+    }
+
+  resolver.Disconnect ("/subresolver/trace-int", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
+  m_gotInt = false;
+  m_traceInt (1);
+  if (m_gotInt)
+    {
+      ok = false;
+    }
+
+  resolver.Connect ("/*/trace-int", 
+		    MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
+  m_gotInt = false;
+  m_traceInt (1);
+  if (!m_gotInt)
+    {
+      ok = false;
+    }
+
+  resolver.Disconnect ("/subresolver/trace-int", 
+		       MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
+  m_gotInt = false;
+  m_traceInt (1);
+  if (m_gotInt)
+    {
+      ok = false;
+    }
+
+
+  
+
+  return ok;
+}
+
+static CompositeTraceResolverTest g_compositeTraceResolverTest;
+
+}//namespace ns3
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/composite-trace-resolver.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,211 @@
+/* -*- 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 COMPOSITE_TRACE_RESOLVER_H
+#define COMPOSITE_TRACE_RESOLVER_H
+
+#include "ns3/callback.h"
+#include "trace-resolver.h"
+#include "callback-trace-source.h"
+#include "uv-trace-source.h"
+#include "sv-trace-source.h"
+#include "fv-trace-source.h"
+#include "terminal-trace-resolver.h"
+
+namespace ns3 {
+
+/**
+ * \brief a helper class to aggregate contained TraceResolver and other trace sources.
+ * \ingroup tracing
+ */
+class CompositeTraceResolver : public TraceResolver
+{
+public:
+  CompositeTraceResolver (TraceContext const &context);
+  virtual ~CompositeTraceResolver ();
+  /**
+   * \param name name of trace source
+   * \param trace a callback trace source
+   * \param context the context associated to this trace source
+   *
+   * Add a callback trace source in this resolver. This trace
+   * source will match the name specified during namespace 
+   * resolution. The TraceContext of this trace source will also
+   * be automatically extended to contain the input context.
+   */
+  template <typename T1, typename T2,
+            typename T3, typename T4,
+            typename T>
+  void Add (std::string name,
+            CallbackTraceSource<T1,T2,T3,T4> &trace, T const &context);
+  /**
+   * \param name name of trace source
+   * \param trace a signed variable trace source
+   * \param context the context associated to this trace source
+   *
+   * Add a signed variable trace source in this resolver. 
+   * This trace source will match the name specified during namespace 
+   * resolution. The TraceContext of this trace source will also
+   * be automatically extended to contain the input context.
+   */
+  template <typename T>
+  void Add (std::string name,
+            SVTraceSource<T> &trace, T const &context);
+  /**
+   * \param name name of trace source
+   * \param trace an unsigned variable trace source
+   * \param context the context associated to this trace source
+   *
+   * Add an unsigned variable trace source in this resolver. 
+   * This trace source will match the name specified during namespace 
+   * resolution. The TraceContext of this trace source will also
+   * be automatically extended to contain the input context.
+   */
+  template <typename T>
+  void Add (std::string name,
+            UVTraceSource<T> &trace, T const &context);
+  /**
+   * \param name name of trace source
+   * \param trace a floating-point variable trace source
+   * \param context the context associated to this trace source
+   *
+   * Add a floating-point variable trace source in this resolver. 
+   * This trace source will match the name specified during namespace 
+   * resolution. The TraceContext of this trace source will also
+   * be automatically extended to contain the input context.
+   */
+  template <typename T>
+  void Add (std::string name,
+            FVTraceSource<T> &trace, T const &context);
+
+  /**
+   * \param name name of child trace resolver
+   * \param createResolver a trace resolver constructor
+   * \param context the context associated to this entry
+   *
+   * Add a child trace resolver to this resolver. This child
+   * trace resolver will match the name specified during
+   * namespace resolution. When this happens, the constructor
+   * will be invoked to create the child trace resolver and
+   * the associated TraceContext will be automatically extended
+   * to contain the input context.
+   */
+  template <typename T>
+  void Add (std::string name, 
+            Callback<TraceResolver *,TraceContext const &> createResolver,
+            T const &context);
+private:
+  template <typename SOURCE, typename CONTEXT>
+  void DoAddTraceSource (std::string name,
+                         SOURCE &traceSource, CONTEXT const &context);
+  template <typename SOURCE>
+  static TraceResolver *CreateTerminalTraceResolver (SOURCE *trace, 
+                                                     TraceContext const &context);
+  void DoAdd (std::string name, 
+              Callback<TraceResolver *,TraceContext const &> createResolver,
+              TraceContext const &context);
+  virtual TraceResolverList DoLookup (std::string id) const;
+
+  struct CallbackTraceSourceItem
+  {
+    std::string name;
+    Callback<TraceResolver *,TraceContext const &> createResolver;
+    TraceContext context;
+  };
+
+  typedef std::list<struct CallbackTraceSourceItem> TraceItems;
+  TraceItems m_items;
+};
+
+}//namespace ns3
+
+namespace ns3 {
+
+template <typename SOURCE, typename CONTEXT>
+void 
+CompositeTraceResolver::DoAddTraceSource (std::string name,
+                                          SOURCE &traceSource, CONTEXT const &context)
+{
+  TraceContext traceContext = GetContext ();
+  traceContext.Add (context);
+  TraceResolver *(*create) (SOURCE *trace, TraceContext const &context);
+  create = &CompositeTraceResolver::CreateTerminalTraceResolver<SOURCE>;
+  Callback<TraceResolver *,TraceContext const &> createResolver = 
+    MakeBoundCallback (create, &traceSource);
+  DoAdd (name, createResolver, traceContext);
+}
+
+template <typename SOURCE>
+TraceResolver *
+CompositeTraceResolver::CreateTerminalTraceResolver (SOURCE *traceSource, 
+                                                     TraceContext const &context)
+{
+  return new TerminalTraceResolver<SOURCE> (*traceSource, context);
+}
+
+
+
+
+template <typename T1, typename T2,
+          typename T3, typename T4,
+          typename T>
+void 
+CompositeTraceResolver::Add (std::string name,
+                             CallbackTraceSource<T1,T2,T3,T4> &trace, 
+                             T const &context)
+{
+  DoAddTraceSource (name, trace, context);
+}
+template <typename T>
+void 
+CompositeTraceResolver::Add (std::string name,
+                             SVTraceSource<T> &trace, T const &context)
+{
+  DoAddTraceSource (name, trace, context);
+}
+template <typename T>
+void 
+CompositeTraceResolver::Add (std::string name,
+                             UVTraceSource<T> &trace, T const &context)
+{
+  DoAddTraceSource (name, trace, context);
+}
+template <typename T>
+void 
+CompositeTraceResolver::Add (std::string name,
+                             FVTraceSource<T> &trace, T const &context)
+{
+  DoAddTraceSource (name, trace, context);
+}
+template <typename T>
+void 
+CompositeTraceResolver::Add (std::string name, 
+                             Callback<TraceResolver *,TraceContext const &> createResolver,
+                             T const &context)
+{
+  TraceContext traceContext = GetContext ();
+  traceContext.Add (context);
+  DoAdd (name, createResolver, traceContext);
+}
+
+
+}//namespace ns3
+
+#endif /* COMPOSITE_TRACE_RESOLVER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/empty-trace-resolver.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,25 @@
+/* -*- 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 "empty-trace-resolver.h"
+
+ns3::EmptyTraceResolver::EmptyTraceResolver (TraceContext const &context)
+  : TraceResolver (context)
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/empty-trace-resolver.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,52 @@
+/* -*- 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 EMPTY_TRACE_RESOLVER_H
+#define EMPTY_TRACE_RESOLVER_H
+
+#include "trace-resolver.h"
+
+namespace ns3 {
+
+class TraceContext;
+
+/**
+ * \brief a TraceResolver instance which does not resolve anything.
+ * \ingroup tracing
+ *
+ * Trying to resolve against this class will yield no matches and no
+ * connections. Returning an instance of this class from a 
+ * CreateTraceResolver method is a hand way of not implementing
+ * any Tracing code.
+ */
+class EmptyTraceResolver : public TraceResolver
+{
+public:
+  /**
+   * \param o necessary context for this class.
+   *
+   * The only constructor exported by this class.
+   */
+  EmptyTraceResolver (TraceContext const &o);
+};
+
+}//namespace ns3
+
+#endif /* EMPTY_TRACE_RESOLVER_H */
--- a/src/common/f-variable-tracer.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 F_VARIABLE_TRACER_H
-#define F_VARIABLE_TRACER_H
-
-#include "ns3/callback.h"
-#include <stdint.h>
-
-namespace ns3 {
-
-class FVariableTracerBase {
-public:
-  typedef Callback<void,double, double> ChangeNotifyCallback;
-
-  FVariableTracerBase () {}
-  FVariableTracerBase (FVariableTracerBase const &o) {}
-  FVariableTracerBase &operator = (FVariableTracerBase const &o) {
-      return *this;
-  }
-
-  ~FVariableTracerBase () {}
-
-  void setCallback(ChangeNotifyCallback callback) {
-      m_callback = callback;
-  }
-protected:
-  void notify (double oldVal, double newVal) {
-      if (oldVal != newVal && !m_callback.IsNull ()) 
-        {
-          m_callback (oldVal, newVal);
-        }
-  }
-private:
-  ChangeNotifyCallback m_callback;
-};
-
-
-}; // namespace ns3
-
-#endif /* F_VARIABLE_TRACER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/fv-trace-source.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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 F_VARIABLE_TRACER_H
+#define F_VARIABLE_TRACER_H
+
+#include "callback-trace-source.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class FVTraceSourceBase {
+public:
+  typedef CallbackTraceSource<double, double> ChangeNotifyCallback;
+
+  FVTraceSourceBase () {}
+  FVTraceSourceBase (FVTraceSourceBase const &o) {}
+  FVTraceSourceBase &operator = (FVTraceSourceBase const &o) {
+      return *this;
+  }
+
+  ~FVTraceSourceBase () {}
+
+  void AddCallback (CallbackBase const & callback, TraceContext const & context) {
+    m_callback.AddCallback (callback, context);
+  }
+  void RemoveCallback (CallbackBase const & callback) {
+    m_callback.RemoveCallback (callback);
+  }
+protected:
+  void notify (double oldVal, double newVal) {
+      if (oldVal != newVal) 
+        {
+          m_callback (oldVal, newVal);
+        }
+  }
+private:
+  ChangeNotifyCallback m_callback;
+};
+
+template <typename T>
+class FVTraceSource : public FVTraceSourceBase 
+{
+public:
+};
+
+}; // namespace ns3
+
+#endif /* F_VARIABLE_TRACER_H */
--- a/src/common/si-variable-tracer.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,238 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 SI_VARIABLE_TRACER_H
-#define SI_VARIABLE_TRACER_H
-
-#include "ns3/callback.h"
-#include <stdint.h>
-
-namespace ns3 {
-
-class SiVariableTracerBase {
-public:
-  typedef Callback<void,int64_t, int64_t> ChangeNotifyCallback;
-
-  SiVariableTracerBase () {}
-  SiVariableTracerBase (SiVariableTracerBase const &o) {}
-  SiVariableTracerBase &operator = (SiVariableTracerBase const &o) {
-      return *this;
-  }
-
-  ~SiVariableTracerBase () {}
-
-  void SetCallback(ChangeNotifyCallback callback) {
-      m_callback = callback;
-  }
-protected:
-  void Notify (int64_t oldVal, int64_t newVal) {
-      if (oldVal != newVal && !m_callback.IsNull ()) 
-        {
-          m_callback (oldVal, newVal);
-        }
-  }
-private:
-  ChangeNotifyCallback m_callback;
-};
-
-template <typename T>
-class UiVariableTracer;
-
-
-/**
- * \brief trace variables of type "signed integer"
- *
- * This template class implements a POD type: it
- * behaves like any other variable of type "signed integer"
- * except that it also reports any changes to its
- * value with its internal callback.
- *
- * To instantiate a 32-bit signed variable (to store
- * a TCP counter for example), you would create a variable of type
- * ns3::UiVariableTracer<int32_t> :
- \code
- #include <stdint.h>
- #include "ns3/si-traced-variable.tcc"
-
- ns3::SiVariableTracer<uint16_t> var;
- \endcode
- * and you would use it like any other variable of type int32_t:
- \code
- var += 12;
- var = 10;
- var = -10;
- \endcode
- */
-template <typename T>
-class SiVariableTracer : public SiVariableTracerBase {
-public:
-  SiVariableTracer ()
-      : m_var (0)
-  {}
-  SiVariableTracer (T const &var) 
-      : m_var (var)
-  {}
-
-  SiVariableTracer &operator = (SiVariableTracer const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  template <typename TT>
-  SiVariableTracer &operator = (SiVariableTracer<TT> const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  template <typename TT>
-  SiVariableTracer &operator = (UiVariableTracer<TT> const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  SiVariableTracer &operator++ () {
-      Assign (Get () + 1);
-      return *this;
-  }
-  SiVariableTracer &operator-- () {
-      Assign (Get () - 1);
-      return *this;
-  }
-  SiVariableTracer operator++ (int) {
-      SiVariableTracer old (*this);
-      ++*this;
-      return old;
-  }
-  SiVariableTracer operator-- (int) {
-      SiVariableTracer old (*this);
-      --*this;
-      return old;
-  }
-  operator T () const {
-      return Get ();
-  }
-
-
-  void Assign (T var) {
-      Notify (m_var, var);
-      m_var = var;
-  }
-  T Get (void) const {
-      return m_var;
-  }
-
-private:
-  T m_var;
-};
-
-template <typename T>
-SiVariableTracer<T> &operator += (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () + rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator -= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () - rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator *= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () * rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator /= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () / rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator <<= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () << rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator >>= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () >> rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator &= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () & rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator |= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () | rhs.Get ());
-  return lhs;
-}
-template <typename T>
-SiVariableTracer<T> &operator ^= (SiVariableTracer<T> &lhs, SiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () ^ rhs.Get ());
-  return lhs;
-}
-
-
-template <typename T, typename U>
-SiVariableTracer<T> &operator += (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () + rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator -= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () - rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator *= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () * rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator /= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () / rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator <<= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () << rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator >>= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () >> rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator &= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () & rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator |= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () | rhs);
-  return lhs;
-}
-template <typename T, typename U>
-SiVariableTracer<T> &operator ^= (SiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () ^ rhs);
-  return lhs;
-}
-
-}; // namespace ns3
-
-#endif /* SI_VARIABLE_TRACER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/sv-trace-source.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,242 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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 SV_TRACE_SOURCE_H
+#define SV_TRACE_SOURCE_H
+
+#include "callback-trace-source.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class SVTraceSourceBase {
+public:
+  typedef CallbackTraceSource<int64_t, int64_t> ChangeNotifyCallback;
+
+  SVTraceSourceBase () {}
+  SVTraceSourceBase (SVTraceSourceBase const &o) {}
+  SVTraceSourceBase &operator = (SVTraceSourceBase const &o) {
+      return *this;
+  }
+
+  ~SVTraceSourceBase () {}
+
+  void AddCallback (CallbackBase const & callback, TraceContext const & context) {
+    m_callback.AddCallback (callback, context);
+  }
+  void RemoveCallback (CallbackBase const & callback) {
+    m_callback.RemoveCallback (callback);
+  }
+protected:
+  void Notify (int64_t oldVal, int64_t newVal) {
+      if (oldVal != newVal) 
+        {
+          m_callback (oldVal, newVal);
+        }
+  }
+private:
+  ChangeNotifyCallback m_callback;
+};
+
+template <typename T>
+class UVTraceSource;
+
+
+/**
+ * \brief trace variables of type "signed integer"
+ * \ingroup tracing
+ *
+ * This template class implements a POD type: it
+ * behaves like any other variable of type "signed integer"
+ * except that it also reports any changes to its
+ * value with its internal callback.
+ *
+ * To instantiate a 32-bit signed variable (to store
+ * a TCP counter for example), you would create a variable of type
+ * ns3::UVTraceSource<int32_t> :
+ \code
+ #include <stdint.h>
+ #include "ns3/sv-trace-source.h"
+
+ ns3::SVTraceSource<uint16_t> var;
+ \endcode
+ * and you would use it like any other variable of type int32_t:
+ \code
+ var += 12;
+ var = 10;
+ var = -10;
+ \endcode
+ */
+template <typename T>
+class SVTraceSource : public SVTraceSourceBase {
+public:
+  SVTraceSource ()
+      : m_var (0)
+  {}
+  SVTraceSource (T const &var) 
+      : m_var (var)
+  {}
+
+  SVTraceSource &operator = (SVTraceSource const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  template <typename TT>
+  SVTraceSource &operator = (SVTraceSource<TT> const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  template <typename TT>
+  SVTraceSource &operator = (UVTraceSource<TT> const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  SVTraceSource &operator++ () {
+      Assign (Get () + 1);
+      return *this;
+  }
+  SVTraceSource &operator-- () {
+      Assign (Get () - 1);
+      return *this;
+  }
+  SVTraceSource operator++ (int) {
+      SVTraceSource old (*this);
+      ++*this;
+      return old;
+  }
+  SVTraceSource operator-- (int) {
+      SVTraceSource old (*this);
+      --*this;
+      return old;
+  }
+  operator T () const {
+      return Get ();
+  }
+
+
+  void Assign (T var) {
+      Notify (m_var, var);
+      m_var = var;
+  }
+  T Get (void) const {
+      return m_var;
+  }
+
+private:
+  T m_var;
+};
+
+template <typename T>
+SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () + rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () - rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () * rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () / rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () << rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () >> rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () & rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () | rhs.Get ());
+  return lhs;
+}
+template <typename T>
+SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, SVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () ^ rhs.Get ());
+  return lhs;
+}
+
+
+template <typename T, typename U>
+SVTraceSource<T> &operator += (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () + rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator -= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () - rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator *= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () * rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator /= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () / rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator <<= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () << rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator >>= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () >> rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator &= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () & rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator |= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () | rhs);
+  return lhs;
+}
+template <typename T, typename U>
+SVTraceSource<T> &operator ^= (SVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () ^ rhs);
+  return lhs;
+}
+
+}; // namespace ns3
+
+#endif /* SV_TRACE_SOURCE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/terminal-trace-resolver.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,66 @@
+/* -*- 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 TERMINAL_TRACE_RESOLVER_H
+#define TERMINAL_TRACE_RESOLVER_H
+
+#include "trace-resolver.h"
+
+namespace ns3 {
+
+class TraceContext;
+
+template <typename T>
+class TerminalTraceResolver : public TraceResolver
+{
+ public:
+  TerminalTraceResolver (T &traceSource, TraceContext const &context);
+ private:
+  virtual void DoConnect (CallbackBase const &cb);
+  virtual void DoDisconnect (CallbackBase const &cb);
+  T &m_traceSource;
+};
+
+}//namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+TerminalTraceResolver<T>::TerminalTraceResolver (T &traceSource, 
+						 TraceContext const &context)
+  : TraceResolver (context),
+    m_traceSource (traceSource)
+{}
+template <typename T>
+void 
+TerminalTraceResolver<T>::DoConnect (CallbackBase const &cb)
+{
+  m_traceSource.AddCallback (cb, GetContext ());
+}
+template <typename T>
+void 
+TerminalTraceResolver<T>::DoDisconnect (CallbackBase const &cb)
+{
+  m_traceSource.RemoveCallback (cb);
+}
+
+}//namespace ns3
+
+#endif /* TERMINAL_TRACE_RESOLVER_H */
--- a/src/common/trace-container.cc	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,188 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 "trace-container.h"
-#include "stream-tracer.h"
-#include <utility>
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-TraceContainer::TraceContainer ()
-{}
-TraceContainer::~TraceContainer ()
-{
-  m_uiList.erase (m_uiList.begin (), m_uiList.end ());
-  m_siList.erase (m_siList.begin (), m_siList.end ());
-  m_fList.erase (m_fList.begin (), m_fList.end ());
-}
-
-void 
-TraceContainer::SetUiVariableCallback (std::string const&name, Callback<void,uint64_t, uint64_t> callback)
-{
-  for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++) 
-    {
-      if ((*i).second == name) 
-        {
-          (*i).first->SetCallback (callback);
-          return;
-        }
-    }
-  NS_ASSERT (false);
-}
-void 
-TraceContainer::SetSiVariableCallback (std::string const&name, Callback<void,int64_t, int64_t> callback)
-{
-  for (SiListI i = m_siList.begin (); i != m_siList.end (); i++) 
-    {
-      if ((*i).second == name) 
-        {
-          (*i).first->SetCallback (callback);
-          return;
-        }
-    }
-  NS_ASSERT (false);
-}
-void 
-TraceContainer::SetFVariableCallback (std::string const&name, Callback<void,double, double> callback)
-{
-  NS_ASSERT (false);
-}
-void 
-TraceContainer::SetStream (std::string const&name, std::ostream *os)
-{
-  for (StreamTracerListI i = m_traceStreamList.begin (); i != m_traceStreamList.end (); i++) 
-    {
-      if ((*i).second == name) 
-        {
-          (*i).first->SetStream (os);
-          return;
-        }
-    }
-  NS_ASSERT (false);
-}
-
-void 
-TraceContainer::RegisterUiVariable (std::string const&name, UiVariableTracerBase *var)
-{
-  // ensure unicity
-  for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          m_uiList.erase (i);
-          break;
-        }
-    }
-  m_uiList.push_back (std::make_pair (var, name));
-}
-void 
-TraceContainer::RegisterSiVariable (std::string const&name, SiVariableTracerBase *var)
-{
-  // ensure unicity
-  for (SiListI i = m_siList.begin (); i != m_siList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          m_siList.erase (i);
-          break;
-        }
-    }
-  m_siList.push_back (std::make_pair (var, name));
-}
-void 
-TraceContainer::RegisterFVariable (std::string const&name, FVariableTracerBase *var)
-{
-  NS_ASSERT (false);
-}
-
-void 
-TraceContainer::RegisterStream (std::string const&name, StreamTracer *stream)
-{
-  // ensure unicity
-  for (StreamTracerListI i = m_traceStreamList.begin (); i != m_traceStreamList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          m_traceStreamList.erase (i);
-          break;
-        }
-    }
-  m_traceStreamList.push_back (std::make_pair (stream,name));
-
-}
-
-void 
-TraceContainer::RegisterCallback (std::string const&name, CallbackTracerBase *tracer)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          m_callbackList.erase (i);
-          break;
-        }
-    }
-  m_callbackList.push_back (std::make_pair (tracer, name));
-}
-
-
-
-
-}; // namespace ns3
-
-#include <iostream>
-void 
-ns3::TraceContainer::PrintDebug (void)
-{
-  if (!m_uiList.empty ()) 
-    {
-      std::cout << "ui var: " << std::endl;
-      for (UiListI i = m_uiList.begin (); i != m_uiList.end (); i++) 
-        {
-          std::cout << "    \"" << (*i).second << "\""<<std::endl;
-        }
-    }
-  if (!m_siList.empty ()) 
-    {
-      std::cout << "si var: " << std::endl;
-      for (SiListI i = m_siList.begin (); i != m_siList.end (); i++) 
-        {
-          std::cout << "    \"" << (*i).second << "\""<<std::endl;
-        }
-    }
-  if (!m_fList.empty ()) 
-    {
-      std::cout << "f var: " << std::endl;
-      for (FListI i = m_fList.begin (); i != m_fList.end (); i++) 
-        {
-          std::cout << "    \"" << (*i).second << "\""<<std::endl;
-        }
-    }
-  if (!m_callbackList.empty ()) 
-    {
-      std::cout << "callback list: "<<std::endl;
-      for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-        {
-          std::cout << "    \"" << i->second << "\""<<std::endl;
-        }
-    }
-}
--- a/src/common/trace-container.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,312 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 TRACE_CONTAINER_H
-#define TRACE_CONTAINER_H
-
-#include "ui-variable-tracer.h"
-#include "si-variable-tracer.h"
-#include "f-variable-tracer.h"
-#include "callback-tracer.h"
-#include "ns3/callback.h"
-#include <list>
-#include <string>
-
-namespace ns3 {
-
-class StreamTracer;
-
-/**
- * \brief register every source of trace events
- *
- * Model authors use the TraceContainer class to register
- * their trace event sources. Model users use the TraceContainer
- * class to connect their trace event listeners to the
- * model trace event sources.
- *
- * TraceContainer can be used to register the following event sources:
- *   - ns3::StreamTracer : can be connected to any std::ostream
- *   - ns3::CallbackTracer: can be connected to any ns3::Callback
- *   - ns3::UiVariableTracer
- *   - ns3::SiVariableTracer
- *   - ns3::FVariableTracer
- *
- * The following sample code shows how you can:
- *   - create trace event sources
- *   - register the trace event sources in a trace container
- *   - set event sinks to each event source
- *  
- * \include samples/main-trace.cc
- */
-class TraceContainer {
-public:
-  TraceContainer ();
-  ~TraceContainer ();
-
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source
-   *
-   * This method targets only event sources which are variables of any unsigned
-   * integer type.
-   */
-  void SetUiVariableCallback (std::string const &name,
-                     Callback<void,uint64_t, uint64_t> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source
-   *
-   * This method targets only event sources which are variables of any signed
-   * integer type.
-   */
-  void SetSiVariableCallback (std::string const &name, Callback<void,int64_t, int64_t> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source
-   *
-   * This method targets only event sources which are variables of any double type.
-   */
-  void SetFVariableCallback (std::string const &name, Callback<void,double, double> callback);
-  /**
-   * \param name the name of the target event source
-   * \param os the output stream being connected to the source trace stream
-   *
-   * This method targets only event sources which are of type StreamTracer.
-   */
-  void SetStream (std::string const &name, std::ostream *os);
-
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source.
-   *
-   * This method targets only event sources which are of type CallbackTracer<T1>
-   */
-  template <typename T1>
-  void SetCallback (std::string const &name, Callback<void,T1> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source.
-   *
-   * This method targets only event sources which are of type CallbackTracer<T1,T2>
-   */
-  template <typename T1, typename T2>
-  void SetCallback (std::string const &name, Callback<void,T1,T2> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source.
-   *
-   * This method targets only event sources which are of type CallbackTracer<T1,T2,T3>
-   */
-  template <typename T1, typename T2, typename T3>
-  void SetCallback (std::string const &name, Callback<void,T1,T2,T3> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source.
-   *
-   * This method targets only event sources which are of type CallbackTracer<T1,T2,T3,T4>
-   */
-  template <typename T1, typename T2, typename T3, typename T4>
-  void SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4> callback);
-  /**
-   * \param name the name of the target event source
-   * \param callback the callback being connected to the target event source.
-   *
-   * This method targets only event sources which are of type CallbackTracer<T1,T2,T3,T4,T5>
-   */
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  void SetCallback (std::string const &name, Callback<void,T1,T2,T3,T4,T5> callback);
-
-  /**
-   * \param name the name of the registered event source
-   * \param var the event source being registered
-   *
-   * This method registers only event sources of type "unsigned integer".
-   */
-  void RegisterUiVariable (std::string const&name, UiVariableTracerBase *var);
-  /**
-   * \param name the name of the registered event source
-   * \param var the event source being registered
-   *
-   * This method registers only event sources of type "signed integer".
-   */
-  void RegisterSiVariable (std::string const&name, SiVariableTracerBase *var);
-  /**
-   * \param name the name of the registered event source
-   * \param var the event source being registered
-   *
-   * This method registers only event sources of type "double".
-   */
-  void RegisterFVariable (std::string const&name, FVariableTracerBase *var);
-  /**
-   * \param name the name of the registered event source
-   * \param stream the event source being registered
-   *
-   * This method registers only event sources of type StreamTracer.
-   */
-  void RegisterStream (std::string const&name, StreamTracer *stream);
-
-  /**
-   * \param name the name of the registeref event source
-   * \param tracer the callback tracer being registered.
-   *
-   * This method registers only event sources of type CallbackTracer
-   */
-  void RegisterCallback (std::string const&name, CallbackTracerBase*tracer);
-
-  /**
-   * Print the list of registered event sources in this container only.
-   */
-  void PrintDebug (void);
-private:
-  typedef std::list<std::pair<UiVariableTracerBase *, std::string> > UiList;
-  typedef std::list<std::pair<UiVariableTracerBase *, std::string> >::iterator UiListI;
-  typedef std::list<std::pair<SiVariableTracerBase *, std::string> > SiList;
-  typedef std::list<std::pair<SiVariableTracerBase *, std::string> >::iterator SiListI;
-  typedef std::list<std::pair<FVariableTracerBase *, std::string> > FList;
-  typedef std::list<std::pair<FVariableTracerBase *, std::string> >::iterator FListI;
-  typedef std::list<std::pair<StreamTracer *, std::string> > StreamTracerList;
-  typedef std::list<std::pair<StreamTracer *, std::string> >::iterator StreamTracerListI;
-  typedef std::list<std::pair<CallbackTracerBase *, std::string> > CallbackList;
-  typedef std::list<std::pair<CallbackTracerBase *, std::string> >::iterator CallbackListI;
-
-  UiList m_uiList;
-  SiList m_siList;
-  FList m_fList;
-  StreamTracerList m_traceStreamList;
-  CallbackList m_callbackList;
-};
-
-}; // namespace ns3
-
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-template <typename T1>
-void 
-TraceContainer::SetCallback (std::string const&name, Callback<void,T1> callback)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          if (i->first->CheckCallbackType (callback))
-            {
-              static_cast<CallbackTracer<T1> *> (i->first)->SetCallback (callback);
-              return;
-            }
-          else
-            {
-              NS_ASSERT (!"non-matching callback");
-            }
-        }
-    }
-  NS_ASSERT (false);
-}
-template <typename T1, typename T2>
-void 
-TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2> callback)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          if (i->first->CheckCallbackType (callback))
-            {
-              static_cast<CallbackTracer<T1,T2> *> (i->first)->SetCallback (callback);
-              return;
-            }
-          else
-            {
-              NS_ASSERT (!"non-matching callback");
-            }
-        }
-    }
-  NS_ASSERT (false);
-}
-template <typename T1, typename T2, typename T3>
-void 
-TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3> callback)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          if (i->first->CheckCallbackType (callback))
-            {
-              static_cast<CallbackTracer<T1,T2,T3> *> (i->first)->SetCallback (callback);
-              return;
-            }
-          else
-            {
-              NS_ASSERT (!"non-matching callback");
-            }
-        }
-    }
-  NS_ASSERT (false);
-}
-template <typename T1, typename T2, typename T3, typename T4>
-void 
-TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4> callback)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          if (i->first->CheckCallbackType (callback))
-            {
-              static_cast<CallbackTracer<T1,T2,T3,T4> *> (i->first)->SetCallback (callback);
-              return;
-            }
-          else
-            {
-              NS_ASSERT (!"non-matching callback");
-            }
-        }
-    }
-  NS_ASSERT (false);
-}
-template <typename T1, typename T2, typename T3, typename T4, typename T5>
-void 
-TraceContainer::SetCallback (std::string const&name, Callback<void,T1,T2,T3,T4,T5> callback)
-{
-  for (CallbackListI i = m_callbackList.begin (); i != m_callbackList.end (); i++) 
-    {
-      if (i->second == name) 
-        {
-          if (i->first->CheckCallbackType (callback))
-            {
-              static_cast<CallbackTracer<T1,T2,T3,T4,T5> *> (i->first)->SetCallback (callback);
-              return;
-            }
-          else
-            {
-              NS_ASSERT (!"non-matching callback");
-            }
-        }
-    }
-  NS_ASSERT (false);
-}
-
-
-}; // namespace ns3
-
-#endif /* TRACED_VARIABLE_CONTAINER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-context.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,320 @@
+/* -*- 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 "trace-context.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+std::vector<uint8_t> TraceContext::m_sizes;
+
+TraceContext::TraceContext ()
+  : m_data (0)
+{}
+TraceContext::TraceContext (TraceContext const &o)
+  : m_data (o.m_data)
+{
+  if (m_data != 0)
+    {
+      m_data->count++;
+    }
+}
+TraceContext const & 
+TraceContext::operator = (TraceContext const &o)
+{
+  if (m_data != 0)
+    {
+      m_data->count--;
+      if (m_data->count == 0)
+        {
+          uint8_t *buffer = (uint8_t *)m_data;
+          delete [] buffer;
+        }
+    }
+  m_data = o.m_data;
+  if (m_data != 0)
+    {
+      m_data->count++;
+    }
+  return *this;
+}
+TraceContext::~TraceContext ()
+{
+  if (m_data != 0)
+    {
+      m_data->count--;
+      if (m_data->count == 0)
+        {
+          uint8_t *buffer = (uint8_t *)m_data;
+          delete [] buffer;
+        }
+    }
+}
+
+uint8_t 
+TraceContext::GetSize (uint8_t uid)
+{
+  return m_sizes[uid];
+}
+
+void 
+TraceContext::Add (TraceContext const &o)
+{
+  if (o.m_data == 0)
+    {
+      return;
+    }
+  uint8_t currentUid;
+  uint16_t i = 0;
+  while (i < o.m_data->size) 
+    {
+      currentUid = o.m_data->data[i];
+      uint8_t size = TraceContext::GetSize (currentUid);
+      uint8_t *selfBuffer = CheckPresent (currentUid);
+      uint8_t *otherBuffer = &(o.m_data->data[i+1]);
+      if (selfBuffer != 0)
+        {
+          if (memcmp (selfBuffer, otherBuffer, size) != 0)
+            {
+              NS_FATAL_ERROR ("You cannot add TraceContexts which "<<
+                              "have different values stored in them.");
+            }
+        }
+      else
+        {
+          DoAdd (currentUid, otherBuffer);
+        }
+      i += 1 + size;
+    }
+}
+
+uint8_t *
+TraceContext::CheckPresent (uint8_t uid) const
+{
+  if (m_data == 0)
+    {
+      return false;
+    }
+  uint8_t currentUid;
+  uint16_t i = 0;
+  do {
+    currentUid = m_data->data[i];
+    uint8_t size = TraceContext::GetSize (currentUid);
+    if (currentUid == uid)
+      {
+        return &m_data->data[i+1];
+      }
+    i += 1 + size;
+  } while (i < m_data->size && currentUid != 0);
+  return 0;
+}
+
+
+bool
+TraceContext::DoAdd (uint8_t uid, uint8_t const *buffer)
+{
+  NS_ASSERT (uid != 0);
+  uint8_t size = TraceContext::GetSize (uid);
+  uint8_t *present = CheckPresent (uid);
+  if (present != 0) {
+    if (memcmp (present, buffer, size) == 0)
+      {
+        return true;
+      }
+    else
+      {
+        return false;
+      }
+  }
+  if (m_data == 0)
+    {
+      uint16_t newSize = 1 + size;
+      uint16_t allocatedSize;
+      if (newSize > 4)
+        {
+          allocatedSize = sizeof (struct Data) + newSize - 4;
+        }
+      else
+        {
+          allocatedSize = sizeof (struct Data);
+        }
+      struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
+      data->size = newSize;
+      data->count = 1;
+      data->data[0] = uid;
+      memcpy (data->data + 1, buffer, size);
+      m_data = data;
+    }
+  else
+    {
+      uint16_t newSize = m_data->size + 1 + size;
+      uint16_t allocatedSize;
+      if (newSize > 4)
+        {
+          allocatedSize = sizeof (struct Data) + newSize - 4;
+        }
+      else
+        {
+          allocatedSize = sizeof (struct Data);
+        }
+      struct Data *data = (struct Data *) (new uint8_t [allocatedSize] ());
+      data->size = newSize;
+      data->count = 1;
+      memcpy (data->data, m_data->data, m_data->size);
+      data->data[m_data->size] = uid;
+      memcpy (data->data + m_data->size + 1, buffer, size);
+      m_data->count--;
+      if (m_data->count == 0)
+        {
+          uint8_t *buffer = (uint8_t *)m_data;
+          delete [] buffer;
+        }
+      m_data = data;
+    }
+  return true;
+}
+bool
+TraceContext::DoGet (uint8_t uid, uint8_t *buffer) const
+{
+  if (m_data == 0)
+    {
+      return false;
+    }
+  uint8_t currentUid;
+  uint16_t i = 0;
+  do {
+    currentUid = m_data->data[i];
+    uint8_t size = TraceContext::GetSize (currentUid);
+    if (currentUid == uid)
+      {
+        memcpy (buffer, &m_data->data[i+1], size);
+        return true;
+      }
+    i += 1 + size;
+  } while (i < m_data->size && currentUid != 0);
+  return false;
+}
+
+uint8_t
+TraceContext::DoGetNextUid (void)
+{
+  static uint8_t uid = 0;
+  if (uid == 0)
+    {
+      m_sizes.push_back (0);
+    }
+  uid++;
+  return uid;
+}
+
+
+}//namespace ns3
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+template <int N>
+class Ctx
+{
+public:
+  Ctx () : m_v (0) {}
+  Ctx (int v) : m_v (v) {}
+  int Get (void) const { return N;}
+private:
+  int m_v;
+};
+
+class TraceContextTest : public Test
+{
+public:
+  TraceContextTest ();
+  virtual bool RunTests (void);
+};
+
+TraceContextTest::TraceContextTest ()
+  : Test ("TraceContext")
+{}
+bool 
+TraceContextTest::RunTests (void)
+{
+  bool ok = true;
+
+  TraceContext ctx;
+  Ctx<0> v0;
+  Ctx<0> v01 = Ctx<0> (1);
+  Ctx<1> v1;
+  Ctx<2> v2;
+  Ctx<3> v3;
+
+  if (ctx.SafeGet (v0))
+    {
+      ok = false;
+    }
+  ctx.Add (v0);
+  ctx.Add (v0);
+  if (ctx.SafeAdd (v01))
+    {
+      ok = false;
+    }
+  ctx.Get (v0);
+  ctx.Add (v1);
+  ctx.Get (v1);
+  ctx.Get (v0);
+  ctx.Get (v1);
+
+  TraceContext copy = ctx;
+  ctx.Get (v0);
+  ctx.Get (v1);
+  copy.Get (v0);
+  copy.Get (v1);
+  copy.Add (v2);
+  copy.Get (v0);
+  copy.Get (v1);
+  copy.Get (v2);
+  ctx.Add (v3);
+  ctx.Get (v0);
+  ctx.Get (v1);
+  ctx.Get (v3);
+
+  if (ctx.SafeGet (v2))
+    {
+      ok = false;
+    }
+  if (copy.SafeGet (v3))
+    {
+      ok = false;
+    }
+  ctx.Add (copy);
+  ctx.Get (v2);
+  if (copy.SafeGet (v3))
+    {
+      ok = false;
+    }
+  copy.Add (ctx);
+  copy.Get (v3);  
+  
+  return ok;
+}
+
+static TraceContextTest g_traceContextTest;
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-context.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,167 @@
+/* -*- 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 TRACE_CONTEXT_H
+#define TRACE_CONTEXT_H
+
+#include <stdint.h>
+#include <vector>
+#include "ns3/fatal-error.h"
+
+namespace ns3 {
+
+/**
+ * \brief Provide context to trace sources
+ * \ingroup tracing
+ *
+ * Instances of this class are used to hold context
+ * for each trace source. Each instance holds a list of
+ * 'contexts'. Trace sinks can lookup these contexts
+ * from this list with the ns3::TraceContext::Get method.
+ *
+ * This class is implemented
+ * using Copy On Write which means that copying unmodified
+ * versions of this class is very cheap. However, modifying
+ * the content of this class through a call 
+ * to ns3::TraceContext::Add will trigger a costly memory
+ * reallocation if needed.
+ */
+class TraceContext
+{
+public:
+  TraceContext ();
+  TraceContext (TraceContext const &o);
+  TraceContext const & operator = (TraceContext const &o);
+  ~TraceContext ();
+
+  /**
+   * \param context add context to list of trace contexts.
+   */
+  template <typename T>
+  void Add (T const &context);
+
+  /**
+   * \param o the other context
+   *
+   * Perform the Union operation (in the sense of set theory) on the
+   * two input lists of elements. This method is used in the
+   * ns3::CallbackTraceSourceSource class when multiple sinks are connected
+   * to a single source to ensure that the source does not need
+   * to store a single TraceContext instance per connected sink.
+   * Instead, all sinks share the same TraceContext.
+   */
+  void Add (TraceContext const &o);
+
+  /**
+   * \param context context to get from this list of trace contexts.
+   *
+   * This method cannot fail. If the requested trace context is not
+   * stored in this TraceContext, then, the program will halt.
+   */
+  template <typename T>
+  void Get (T &context) const;
+private:
+  friend class TraceContextTest;
+  // used exclusively for testing code.
+  template <typename T>
+  bool SafeGet (T &context) const;
+  template <typename T>
+  bool SafeAdd (T &context);
+
+  template <typename T>
+  static uint8_t GetUid (void);
+  template <typename T>
+  static uint8_t GetNextUid (void);
+  static uint8_t DoGetNextUid (void);
+  static uint8_t GetSize (uint8_t uid);
+  uint8_t *CheckPresent (uint8_t uid) const;
+  bool DoAdd (uint8_t uid, uint8_t const *buffer);
+  bool DoGet (uint8_t uid, uint8_t *buffer) const;
+
+  static std::vector<uint8_t> m_sizes;
+  struct Data {
+    uint16_t count;
+    uint16_t size;
+    uint8_t data[4];
+  } * m_data;
+};
+
+}//namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void 
+TraceContext::Add (T const &context)
+{
+  uint8_t *data = (uint8_t *) &context;
+  bool ok = DoAdd (TraceContext::GetUid<T> (), data);
+  if (!ok)
+    {
+      NS_FATAL_ERROR ("Trying to add twice the same type with different values is invalid.");
+    }
+}
+template <typename T>
+void
+TraceContext::Get (T &context) const
+{
+  uint8_t *data = (uint8_t *) &context;
+  bool found = DoGet (TraceContext::GetUid<T> (), data);
+  if (!found)
+    {
+      NS_FATAL_ERROR ("Type not stored in TraceContext");
+    }
+}
+template <typename T>
+bool
+TraceContext::SafeGet (T &context) const
+{
+  uint8_t *data = (uint8_t *) &context;
+  bool found = DoGet (TraceContext::GetUid<T> (), data);
+  return found;
+}
+template <typename T>
+bool
+TraceContext::SafeAdd (T &context)
+{
+  uint8_t *data = (uint8_t *) &context;
+  bool ok = DoAdd (TraceContext::GetUid<T> (), data);
+  return ok;
+}
+template <typename T>
+uint8_t
+TraceContext::GetUid (void)
+{
+  static uint8_t uid = GetNextUid<T> ();
+  return uid;
+}
+
+template <typename T>
+uint8_t
+TraceContext::GetNextUid (void)
+{
+  uint8_t uid = DoGetNextUid ();
+  m_sizes.push_back (sizeof (T));
+  return uid;
+}
+
+}//namespace ns3
+
+#endif /* TRACE_CONTEXT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-resolver.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,104 @@
+/* -*- 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 "trace-resolver.h"
+
+namespace ns3 {
+
+TraceResolver::TraceResolver (TraceContext const &context)
+  : m_context (context)
+{}
+
+TraceResolver::~TraceResolver ()
+{}
+
+TraceContext const &
+TraceResolver::GetContext (void) const
+{
+  return m_context;
+}
+
+void 
+TraceResolver::Connect (std::string path, CallbackBase const &cb)
+{
+  std::string::size_type cur = 1;
+  // check that first char is "/"
+  std::string::size_type next = path.find ("/", cur);
+  std::string element = std::string (path, cur, next-1);
+  TraceResolverList resolverList = DoLookup (element);
+  for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
+    {
+      TraceResolver *resolver = *i;
+      if (next == std::string::npos) 
+	{
+	  // we really break the recursion here.
+	  resolver->DoConnect (cb);
+	}
+      else
+	{
+	  std::string subpath = std::string (path, next, std::string::npos);
+          resolver->Connect (subpath, cb);
+	}
+      delete resolver;
+    }
+  resolverList.erase (resolverList.begin (), resolverList.end ());
+}
+
+void 
+TraceResolver::Disconnect (std::string path, CallbackBase const &cb)
+{
+  std::string::size_type cur = 1;
+  // check that first char is "/"
+  std::string::size_type next = path.find ("/", cur);
+  std::string element = std::string (path, cur, next-1);
+  TraceResolverList resolverList = DoLookup (element);
+  for (TraceResolverList::iterator i = resolverList.begin (); i != resolverList.end (); i++)
+    {
+      TraceResolver *resolver = *i;
+      if (next == std::string::npos) 
+	{
+	  // we really break the recursion here.
+	  resolver->DoDisconnect (cb);
+	}
+      else
+	{
+	  std::string subpath = std::string (path, next, std::string::npos);
+          resolver->Disconnect (subpath, cb);
+	}
+      delete resolver;
+    }
+  resolverList.erase (resolverList.begin (), resolverList.end ());
+}
+
+TraceResolver::TraceResolverList 
+TraceResolver::DoLookup (std::string id) const
+{
+  return TraceResolverList ();
+}
+void 
+TraceResolver::DoConnect (CallbackBase const &cb)
+{}
+
+void 
+TraceResolver::DoDisconnect (CallbackBase const &cb)
+{}
+
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-resolver.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,119 @@
+/* -*- 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 TRACE_RESOLVER_H
+#define TRACE_RESOLVER_H
+
+#include <string>
+#include <list>
+#include "trace-context.h"
+
+namespace ns3 {
+
+class CallbackBase;
+
+/**
+ * \brief the base class which is used to incremental perform trace
+ *        namespace resolution.
+ * \ingroup tracing
+ *
+ * This class provides a public API to the ns3::TraceRoot object:
+ *   - ns3::TraceResolver::Connect
+ *   - ns3::TraceResolver::Disconnect
+ *
+ * It also provides an API for its subclasses. Each subclass should 
+ * implement one of:
+ *   - ns3::TraceResolver::DoLookup
+ *   - ns3::TraceResolver::DoConnect and ns3::TraceResolver::DoDisconnect
+ * Each subclass must also provide an ns3::TraceContext to the TraceResolver
+ * constructor. Finally, each subclass can access the ns3::TraceContext 
+ * associated to this  ns3::TraceResolver through the 
+ * ns3::TraceResolver::GetContext method.
+ */
+class TraceResolver
+{
+public:
+  virtual ~TraceResolver ();
+  /**
+   * \param path the namespace path to resolver
+   * \param cb the callback to connect to the matching namespace
+   *
+   * This method is typically invoked by ns3::TraceRoot but advanced
+   * users could also conceivably call it directly if they want to
+   * skip the ns3::TraceRoot.
+   */
+  void Connect (std::string path, CallbackBase const &cb);
+  /**
+   * \param path the namespace path to resolver
+   * \param cb the callback to disconnect in the matching namespace
+   *
+   * This method is typically invoked by ns3::TraceRoot but advanced
+   * users could also conceivably call it directly if they want to
+   * skip the ns3::TraceRoot.
+   */
+  void Disconnect (std::string path, CallbackBase const &cb);
+protected:
+  /**
+   * \param context the context used to initialize this TraceResolver.
+   *
+   * Every subclass must call this constructor
+   */
+  TraceResolver (TraceContext const &context);
+  /**
+   * \returns the ns3::TraceContext stored in this ns3::TraceResolver.
+   *
+   * Subclasses usually invoke this method to get access to the
+   * TraceContext stored here to pass it down to the TraceResolver
+   * constructors invoked from within the DoLookup method.
+   */
+  TraceContext const &GetContext (void) const;
+  typedef std::list<TraceResolver *> TraceResolverList;
+private:
+  TraceResolver ();
+  /**
+   * \param id the id to resolve. This is supposed to be
+   * one element of the global tracing namespace.
+   * \returns a list of reslvers which match the input namespace element
+   *
+   * A subclass which overrides this method should return a potentially
+   * empty list of pointers to ns3::TraceResolver instances which match
+   * the input namespace element. Each of these TraceResolver should be
+   * instanciated with a TraceContext which holds enough context
+   * information to identify the type of the TraceResolver.
+   */
+  virtual TraceResolverList DoLookup (std::string id) const;
+  /**
+   * \param cb callback to connect
+   *
+   * This method is invoked on leaf trace resolvers.
+   */
+  virtual void DoConnect (CallbackBase const &cb);
+  /**
+   * \param cb callback to disconnect
+   *
+   * This method is invoked on leaf trace resolvers.
+   */
+  virtual void DoDisconnect (CallbackBase const &cb);
+  TraceContext m_context;
+};
+
+}//namespace ns3
+
+#endif /* TRACE_RESOLVER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-root.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,54 @@
+/* -*- 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 "trace-root.h"
+#include "ns3/composite-trace-resolver.h"
+#include "ns3/trace-context.h"
+
+namespace ns3 {
+
+void 
+TraceRoot::Connect (std::string path, CallbackBase const &cb)
+{
+  TraceResolver *resolver = GetComposite ();
+  resolver->Connect (path, cb);
+}
+void 
+TraceRoot::Disconnect (std::string path, CallbackBase const &cb)
+{
+  TraceResolver *resolver = GetComposite ();
+  resolver->Disconnect (path, cb);
+}
+void 
+TraceRoot::Register (std::string name, 
+                     Callback<TraceResolver *,TraceContext const &> createResolver)
+{
+  CompositeTraceResolver *resolver = GetComposite ();
+  resolver->Add (name, createResolver, TraceRoot::NOTHING);
+}
+
+CompositeTraceResolver *
+TraceRoot::GetComposite (void)
+{
+  static CompositeTraceResolver resolver = CompositeTraceResolver (TraceContext ());
+  return &resolver;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-root.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,255 @@
+/* -*- 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 TRACE_ROOT_H
+#define TRACE_ROOT_H
+
+#include <string>
+#include "ns3/callback.h"
+
+/**
+ * \defgroup tracing Tracing
+ *
+ * The low-level tracing framework is built around a few very simple
+ * concepts:
+ *   - There can be any number of trace source objects. Each trace source
+ *     object can generate any number of trace events. The current
+ *     trace source objects are: ns3::CallbackTraceSourceSource, ns3::UVTraceSource,
+ *     ns3::SVTraceSource, and, ns3::FVTraceSource.
+ *   - Each trace source can be connected to any number of trace sinks.
+ *     A trace sink is a ns3::Callback with a very special signature. Its
+ *     first argument is always a ns3::TraceContext.
+ *   - Every trace source is uniquely identified by a ns3::TraceContext. Every
+ *     trace sink can query a ns3::TraceContext for information. This allows
+ *     a trace sink which is connected to multiple trace sources to identify
+ *     from which source each event is coming from.
+ *
+ * To allow the user to connect his own trace sinks to each trace source
+ * defined by any of the models he is using, the tracing framework defines
+ * a hierarchical namespace. The root of this namespace is accessed through
+ * the ns3::TraceRoot class. The namespace is represented as a string made
+ * of multiple elements, each of which is separated from the other elements
+ * by the '/' character. A namespace string always starts with a '/'.
+ *
+ * By default, the simulation models provide a '/nodes' tracing root. This
+ * '/nodes' namespace is structured as follows:
+ * \code
+ *  /nodes/n/udp
+ *  /nodes/n/ipv4
+ *               /tx
+ *               /rx
+ *               /drop
+ *               /interfaces/n/netdevice
+ *                 (NetDevice only)    /queue/
+ *                                           /enque
+ *                                           /deque
+ *                                           /drop
+ *  /nodes/n/arp
+ * \endcode
+ *
+ * The 'n' element which follows the /nodes and /interfaces namespace elements
+ * identify a specific node and interface through their index within the 
+ * ns3::NodeList and ns3::Ipv4 objects respectively.
+ *
+ * To connect a trace sink to a trace source identified by a namespace string,
+ * a user can call the ns3::TraceRoot::Connect method (the ns3::TraceRoot::Disconnect
+ * method does the symmetric operation). This connection method can accept
+ * fully-detailed namespace strings but it can also perform pattern matching
+ * on the user-provided namespace strings to connect multiple trace sources
+ * to a single trace sink in a single connection operation.
+ *
+ * The syntax of the pattern matching rules are loosely based on regular 
+ * expressions:
+ *   - the '*' character matches every element
+ *   - the (a|b) construct matches element 'a' or 'b'
+ *   - the [ss-ee] construct matches all numerical values which belong
+ *     to the interval which includes ss and ee
+ *
+ * For example, the user could use the following to connect a single sink
+ * to the ipv4 tx, rx, and drop trace events:
+ *
+ * \code
+ * void MyTraceSink (TraceContext const &context, Packet &packet);
+ * TraceRoot::Connect ("/nodes/ * /ipv4/ *", MakeCallback (&MyTraceSink));
+ * \endcode
+ *
+ * Of course, this code would work only if the signature of the trace sink
+ * is exactly equal to the signature of all the trace sources which match
+ * the namespace string (if one of the matching trace source does not match
+ * exactly, a fatal error will be triggered at runtime during the connection
+ * process). The ns3::TraceContext extra argument contains
+ * information on where the trace source is located in the namespace tree.
+ * In that example, if there are multiple nodes in this scenario, each
+ * call to the MyTraceSink function would receive a different TraceContext,
+ * each of which would contain a different NodeList::Index object.
+ *
+ * It is important to understand exactly what an ns3::TraceContext
+ * is. It is a container for a number of type instances. Each instance of
+ * a ns3::TraceContext contains one and only one instance of a given type.
+ * ns3::TraceContext::Add can be called to add a type instance into a 
+ * TraceContext instance and ns3::TraceContext::Get can be called to get
+ * a copy of a type instance stored into the ns3::TraceContext. If ::Get
+ * cannot retrieve the requested type, a fatal error is triggered at
+ * runtime. The values stored into an ns3::TraceContext attached to a 
+ * trace source are automatically determined during the namespace
+ * resolution process. To retrieve a value from a ns3::TraceContext, the
+ * code can be as simple as this:
+ * \code
+ * void MyTraceSink (TraceContext const &context, Packet &packet)
+ * {
+ *   NodeList::Index index;
+ *   context.Get (index);
+ *   std::cout << "node id=" << NodeList::GetNode (index)->GetId () << std::endl;
+ * }
+ * \endcode
+ *
+ * To define new trace sources, a model author needs to instante one trace source
+ * object for each kind of tracing event he wants to export. The trace source objects
+ * currently defined are:
+ *  - ns3::CallbackTraceSourceSource: this trace source can be used to convey any kind of 
+ *    trace event to the user. It is a functor, that is, it is a variable
+ *    which behaves like a function which will forward every event to every
+ *    connected trace sink (i.e., ns3::Callback). This trace source takes
+ *    up to four arguments and forwards these 4 arguments together with the
+ *    ns3::TraceContext which identifies this trace source to the connected
+ *    trace sinks.
+ *  - ns3::UVTraceSource: this trace source is used to convey key state variable
+ *    changes to the user. It behaves like a normal integer unsigned variable:
+ *    you can apply every normal arithmetic operator to it. It will forward
+ *    every change in the value of the variable back to every connected trace 
+ *    sink by providing a TraceContext, the old value and the new value.
+ *  - ns3::SVTraceSource: this is the signed integer equivalent of 
+ *    ns3::UVTraceSource.
+ *  - ns3::FVTraceSource: this is the floating point equivalent of 
+ *    ns3::UVTraceSource and ns3::SVTraceSource.
+ *
+ * Once the model author has instantiated these objects and has wired them
+ * in his simulation code (that is, he calls them wherever he wants to
+ * trigger a trace event), he needs to hook these trace sources into the
+ * global tracing namespace. The first step to do this is to define a method
+ * which returns a pointer to a ns3::TraceResolver object and which takes
+ * as argument a reference to a const ns3::TraceContext. The name of this method
+ * depends on how you will hook into the global tracing namespace. Before
+ * we get there, you need to implement this method. To do this, you could
+ * attempt to do everything by hand: define a subclass of the 
+ * ns3::TraceResolver base class and implement its DoConnect, DoDisconnect
+ * and DoLookup methods. Because doing this can be a bit tedious, our
+ * tracing framework provides a number of helper template classes which
+ * should save you from having to implement your own in most cases:
+ *   - ns3::CompositeTraceResolver: this subclass of ns3::TraceResolver
+ *     can be used to aggregate together multiple trace sources and
+ *     multiple other ns3::TraceResolver instances.
+ *   - ns3::ArrayTraceResolver: this subclass of ns3::TraceResolver
+ *     can be used to match any number of elements within an array
+ *     where every element is identified by its index.
+ *
+ * Once you can instantiate your own ns3::TraceResolver object instance,
+ * you have to hook it up into the global namespace. There are two ways 
+ * to do this:
+ *   - you can hook your ns3::TraceResolver creation method as a new trace 
+ *     root by using the ns3::TraceRoot::Register method
+ *   - you can hook your new ns3::TraceResolver creation method into 
+ *     the container of your model.
+ *     For example, if you wrote a new l3 protocol, all you have to do
+ *     to hook into your container L3Demux class is to implement
+ *     the pure virtual method inherited from the L3Protocol class
+ *     whose name is ns3::L3protocol::CreateTraceResolver.
+ *
+ * If you really want to have fun and implement your own ns3::TraceResolver 
+ * subclass, you need to understand the basic Connection and Disconnection
+ * algorithm. The code of that algorithm is wholy contained in the
+ * ns3::TraceResolver::Connect and ns3::TraceResolver::Disconnect methods.
+ * The idea is that we recursively parse the input namespace string by removing
+ * the first namespace element. This element is 'resolved' is calling
+ * the ns3::TraceResolver::DoLookup method which returns a list of
+ * TraceResolver instances. Each of the returned TraceResolver instance is
+ * then given what is left of the namespace by calling ns3::TraceResolver::Connect
+ * until the last namespace element is processed. At this point, we invoke
+ * the ns3::TraceResolver::DoConnect or ns3::TraceResolver::DoDisconnect 
+ * methods to break the recursion. A good way to understand this algorithm
+ * is to trace its behavior. Let's say that you want to connect to
+ * '/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *'. It would generate
+ * the following call traces:
+ *
+ * \code
+ * TraceRoot::Connect (/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *);
+ * resolver = NodeList::CreateTraceResolver ();
+ * resolver->Connect (/nodes/ * /ipv4/interfaces/ * /netdevice/queue/ *);
+ * list = CompositeTraceResolver::DoLookup ('nodes');
+ * resolver->Connect (/ * /ipv4/interfaces/ * /netdevice/queue/ *);
+ * list = ArrayTraceResolver::DoLookup ('*');
+ * resolver->Connect ('/ipv4/interfaces/ * /netdevice/queue/ *');
+ * list = CompositeTraceResolver::DoLookup ('ipv4');
+ * resolver->Connect ('/interfaces/ * /netdevice/queue/ *');
+ * list = CompositeTraceResolver::DoLookup ('interfaces');
+ * resolver->Connect ('/ * /netdevice/queue/ *');
+ * list = ArrayTraceResolver::DoLookup ('*');
+ * resolver->Connect ('/netdevice/queue/ *');
+ * list = CompositeTraceResolver::DoLookup ('netdevice');
+ * resolver->Connect ('/queue/ *');
+ * list = CompositeTraceResolver::DoLookup ('queue');
+ * resolver->Connect ('/ *');
+ * list = CompositeTraceResolver::DoLookup ('*');
+ * resolver->DoConnect ();
+ * \endcode
+ *
+ * This namespace resolution algorithm makes sure that each subpart of the
+ * namespace is resolved separately by each component. It allows you to
+ * never have to know the entire namespace structure to resolve a namespace
+ * string. All namespace knowledge is local which makes it very easy to plug
+ * in new components and have them extend the global tracing namespace.
+ *
+ * What is central to this namespace parsing and resolution algorithm is the
+ * construction of an ns3::TraceContext for each trace source during the 
+ * connection process. The root trace context is intialized to be empty and
+ * TraceResolver::DoLookup method is responsible for incrementally constructing
+ * the TraceContext assigned to each terminal TraceSource object.
+ */
+
+namespace ns3 {
+
+class CompositeTraceResolver;
+class TraceResolver;
+class TraceContext;
+class CallbackBase;
+
+/**
+ * \brief The main class used to access tracing functionality for
+ * a user.
+ *
+ * \ingroup tracing
+ */
+class TraceRoot
+{
+public:
+  static void Connect (std::string path, CallbackBase const &cb);
+  static void Disconnect (std::string path, CallbackBase const &cb);
+  static void Register (std::string name, 
+                        Callback<TraceResolver *,TraceContext const &> createResolver);
+private:
+  static CompositeTraceResolver *GetComposite (void);
+  enum TraceType {
+    NOTHING,
+  };
+};
+
+}// namespace ns3
+
+#endif /* TRACE_ROOT_H */
--- a/src/common/ui-variable-tracer.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 UI_VARIABLE_TRACER_H
-#define UI_VARIABLE_TRACER_H
-
-#include "ns3/callback.h"
-#include <stdint.h>
-
-namespace ns3 {
-
-class UiVariableTracerBase {
-public:
-  typedef Callback<void, uint64_t, uint64_t> ChangeNotifyCallback;
-
-  UiVariableTracerBase ()
-      : m_callback () {}
-  /* We don't want to copy the base callback. Only setCallback on
-   * a specific instance will do something to it. */
-  UiVariableTracerBase (UiVariableTracerBase const &o) 
-      : m_callback () {}
-  UiVariableTracerBase &operator = (UiVariableTracerBase const &o) {
-      return *this;
-  }
-  ~UiVariableTracerBase () {}
-
-  void SetCallback(ChangeNotifyCallback callback) {
-      m_callback = callback;
-  }
-protected:
-  void Notify (uint64_t oldVal, uint64_t newVal) {
-      if (oldVal != newVal && !m_callback.IsNull ()) 
-        {
-          m_callback (oldVal, newVal);
-        }
-  }
-private:
-  ChangeNotifyCallback m_callback;
-};
-
-template <typename T>
-class SiVariableTracer;
-
-
-/**
- * \brief trace variables of type "unsigned integer"
- *
- * This template class implements a POD type: it
- * behaves like any other variable of type "unsigned integer"
- * except that it also reports any changes to its
- * value with its internal callback.
- *
- * To instantiate a 32-bit unsigned variable (to store
- * a TCP counter for example), you would create a variable of type
- * ns3::UiVariableTracer<uint32_t> :
- \code
- #include <stdint.h>
- #include "ns3/ui-traced-variable.tcc"
-
- ns3::UiVariableTracer<uint32_t> var;
- \endcode
- * and you would use it like any other variable of type uint32_t:
- \code
- var += 12;
- var = 10;
- \endcode
- */
-template <typename T>
-class UiVariableTracer : public UiVariableTracerBase {
-public:
-  UiVariableTracer ()
-      : m_var ()
-  {}
-  UiVariableTracer (T const &var) 
-      : m_var (var)
-  {}
-
-  UiVariableTracer &operator = (UiVariableTracer const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  template <typename TT>
-  UiVariableTracer &operator = (UiVariableTracer<TT> const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  template <typename TT>
-  UiVariableTracer &operator = (SiVariableTracer<TT> const &o) {
-      Assign (o.Get ());
-      return *this;
-  }
-  UiVariableTracer &operator++ () {
-      Assign (Get () + 1);
-      return *this;
-  }
-  UiVariableTracer &operator-- () {
-      Assign (Get () - 1);
-      return *this;
-  }
-  UiVariableTracer operator++ (int) {
-      UiVariableTracer old (*this);
-      ++*this;
-      return old;
-  }
-  UiVariableTracer operator-- (int) {
-      UiVariableTracer old (*this);
-      --*this;
-      return old;
-  }
-  operator T () const {
-      return Get ();
-  }
-
-
-  void Assign (T var) {
-      Notify (m_var, var);
-      m_var = var;
-  }
-  T Get (void) const {
-      return m_var;
-  }
-
-private:
-  T m_var;
-};
-
-template <typename T>
-UiVariableTracer<T> &operator += (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () + rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator -= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () - rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator *= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () * rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator /= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () / rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator <<= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () << rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator >>= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () >> rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator &= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () & rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator |= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () | rhs.Get ());
-  return lhs;
-}
-template <typename T>
-UiVariableTracer<T> &operator ^= (UiVariableTracer<T> &lhs, UiVariableTracer<T> const &rhs) {
-  lhs.Assign (lhs.Get () ^ rhs.Get ());
-  return lhs;
-}
-
-
-template <typename T, typename U>
-UiVariableTracer<T> &operator += (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () + rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator -= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () - rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator *= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () * rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator /= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () / rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator <<= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () << rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator >>= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () >> rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator &= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () & rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator |= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () | rhs);
-  return lhs;
-}
-template <typename T, typename U>
-UiVariableTracer<T> &operator ^= (UiVariableTracer<T> &lhs, U const &rhs) {
-  lhs.Assign (lhs.Get () ^ rhs);
-  return lhs;
-}
-
-}; // namespace ns3
-
-#endif /* UI_VARIABLE_TRACER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/uv-trace-source.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,245 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006 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 UV_TRACE_SOURCE_H
+#define UV_TRACE_SOURCE_H
+
+#include "callback-trace-source.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class UVTraceSourceBase {
+public:
+  typedef CallbackTraceSource<uint64_t, uint64_t> ChangeNotifyCallback;
+
+  UVTraceSourceBase ()
+      : m_callback () {}
+  /* We don't want to copy the base callback. Only setCallback on
+   * a specific instance will do something to it. */
+  UVTraceSourceBase (UVTraceSourceBase const &o) 
+      : m_callback () {}
+  UVTraceSourceBase &operator = (UVTraceSourceBase const &o) {
+      return *this;
+  }
+  ~UVTraceSourceBase () {}
+
+  void AddCallback (CallbackBase const & callback, TraceContext const & context) {
+    m_callback.AddCallback (callback, context);
+  }
+  void RemoveCallback (CallbackBase const & callback) {
+    m_callback.RemoveCallback (callback);
+  }
+
+protected:
+  void Notify (uint64_t oldVal, uint64_t newVal) {
+      if (oldVal != newVal) 
+        {
+          m_callback (oldVal, newVal);
+        }
+  }
+private:
+  ChangeNotifyCallback m_callback;
+};
+
+template <typename T>
+class SVTraceSource;
+
+
+/**
+ * \brief trace variables of type "unsigned integer"
+ * \ingroup tracing
+ *
+ * This template class implements a POD type: it
+ * behaves like any other variable of type "unsigned integer"
+ * except that it also reports any changes to its
+ * value with its internal callback.
+ *
+ * To instantiate a 32-bit unsigned variable (to store
+ * a TCP counter for example), you would create a variable of type
+ * ns3::UVTraceSource<uint32_t> :
+ \code
+ #include <stdint.h>
+ #include "ns3/uv-trace-source.h"
+
+ ns3::UVTraceSource<uint32_t> var;
+ \endcode
+ * and you would use it like any other variable of type uint32_t:
+ \code
+ var += 12;
+ var = 10;
+ \endcode
+ */
+template <typename T>
+class UVTraceSource : public UVTraceSourceBase {
+public:
+  UVTraceSource ()
+      : m_var ()
+  {}
+  UVTraceSource (T const &var) 
+      : m_var (var)
+  {}
+
+  UVTraceSource &operator = (UVTraceSource const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  template <typename TT>
+  UVTraceSource &operator = (UVTraceSource<TT> const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  template <typename TT>
+  UVTraceSource &operator = (SVTraceSource<TT> const &o) {
+      Assign (o.Get ());
+      return *this;
+  }
+  UVTraceSource &operator++ () {
+      Assign (Get () + 1);
+      return *this;
+  }
+  UVTraceSource &operator-- () {
+      Assign (Get () - 1);
+      return *this;
+  }
+  UVTraceSource operator++ (int) {
+      UVTraceSource old (*this);
+      ++*this;
+      return old;
+  }
+  UVTraceSource operator-- (int) {
+      UVTraceSource old (*this);
+      --*this;
+      return old;
+  }
+  operator T () const {
+      return Get ();
+  }
+
+
+  void Assign (T var) {
+      Notify (m_var, var);
+      m_var = var;
+  }
+  T Get (void) const {
+      return m_var;
+  }
+
+private:
+  T m_var;
+};
+
+template <typename T>
+UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () + rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () - rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () * rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () / rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () << rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () >> rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () & rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () | rhs.Get ());
+  return lhs;
+}
+template <typename T>
+UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, UVTraceSource<T> const &rhs) {
+  lhs.Assign (lhs.Get () ^ rhs.Get ());
+  return lhs;
+}
+
+
+template <typename T, typename U>
+UVTraceSource<T> &operator += (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () + rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator -= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () - rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator *= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () * rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator /= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () / rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator <<= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () << rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator >>= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () >> rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator &= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () & rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator |= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () | rhs);
+  return lhs;
+}
+template <typename T, typename U>
+UVTraceSource<T> &operator ^= (UVTraceSource<T> &lhs, U const &rhs) {
+  lhs.Assign (lhs.Get () ^ rhs);
+  return lhs;
+}
+
+}; // namespace ns3
+
+#endif /* UV_TRACE_SOURCE_H */
--- a/src/common/variable-tracer-test.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/common/variable-tracer-test.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -19,8 +19,9 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
-#include "ui-variable-tracer.h"
-#include "si-variable-tracer.h"
+#include "uv-trace-source.h"
+#include "sv-trace-source.h"
+#include "trace-context.h"
 #include "ns3/test.h"
 #include "ns3/callback.h"
 
@@ -29,7 +30,7 @@
 
 class Foo {
 public:
-  void Notify (uint64_t oldVal, uint64_t newVal) {}
+  void Notify (TraceContext const &contex, uint64_t oldVal, uint64_t newVal) {}
 };
 
 class VariableTracerTest: public Test {
@@ -42,11 +43,11 @@
 void
 VariableTracerTest::RunUnsignedTests (void)
 {
-  UiVariableTracer<uint32_t> var, ovar, tmp;
+  UVTraceSource<uint32_t> var, ovar, tmp;
   uint32_t utmp;
   Foo *foo = new Foo ();
   
-  var.SetCallback (MakeCallback (&Foo::Notify, foo));
+  var.AddCallback (MakeCallback (&Foo::Notify, foo), TraceContext ());
 
   var = 10;
   ovar = var;
@@ -227,10 +228,10 @@
   uitmp = utmp;
   utmp = uitmp;
 
-  UiVariableTracer<unsigned short> uvar = 10;
-  UiVariableTracer<unsigned int> uivar = 5;
-  SiVariableTracer<short> svar = 5;
-  SiVariableTracer<int> sivar = 5;
+  UVTraceSource<unsigned short> uvar = 10;
+  UVTraceSource<unsigned int> uivar = 5;
+  SVTraceSource<short> svar = 5;
+  SVTraceSource<int> sivar = 5;
   uvar = svar;
   svar = uvar;
   uvar += svar;
--- a/src/core/callback-test.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/core/callback-test.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -47,6 +47,16 @@
   return a;
 }
 
+void *Test9 (bool *a)
+{
+  return a;
+}
+
+void *Test10 (bool *a, int const & b)
+{
+  return a;
+}
+
 class CallbackTest : public ns3::Test {
 private:
   bool m_test1;
@@ -147,9 +157,9 @@
   b0 = B (this, &CallbackTest::Test2);
   C c0 = C (this, &CallbackTest::Test3);
   D d0 = D (this, &CallbackTest::Test4);
-  E e0 = E (&Test5);
-  F f0 = F (&Test6);
-  G g0 = G (&Test7);
+  E e0 = E (&Test5, true, true);
+  F f0 = F (&Test6, true, true);
+  G g0 = G (&Test7, true, true);
 
   a0 ();
   b0 ();
@@ -190,6 +200,13 @@
     {
       ok = false;
     }
+
+
+  MakeBoundCallback (&Test7, 0);
+  bool v;
+  MakeBoundCallback (&Test9, &v);
+  MakeBoundCallback (&Test10, &v);
+
   return ok;
 }
 
--- a/src/core/callback.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/core/callback.h	Sun Mar 18 14:06:51 2007 -0700
@@ -60,6 +60,7 @@
 class CallbackImplBase {
 public:
   virtual ~CallbackImplBase () {}
+  virtual bool IsEqual (CallbackImplBase const *other) const = 0;
 };
 
 // declare the CallbackImpl class
@@ -134,6 +135,19 @@
   R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
       return m_functor (a1,a2,a3,a4,a5);
   }
+  virtual bool IsEqual (CallbackImplBase const *other) const {
+    FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *otherDerived = 
+      dynamic_cast<FunctorCallbackImpl<T,R,T1,T2,T3,T4,T5> const *> (other);
+    if (otherDerived == 0)
+      {
+        return false;
+      }
+    else if (otherDerived->m_functor != m_functor)
+      {
+        return false;
+      }
+    return true;
+  }
 private:
   T m_functor;
 };
@@ -163,6 +177,20 @@
   R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
       return ((*m_objPtr).*m_memPtr) (a1,a2,a3,a4,a5);
   }
+  virtual bool IsEqual (CallbackImplBase const *other) const {
+    MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *otherDerived = 
+      dynamic_cast<MemPtrCallbackImpl<OBJ_PTR,MEM_PTR,R,T1,T2,T3,T4,T5> const *> (other);
+    if (otherDerived == 0)
+      {
+        return false;
+      }
+    else if (otherDerived->m_objPtr != m_objPtr ||
+             otherDerived->m_memPtr != m_memPtr)
+      {
+        return false;
+      }
+    return true;
+  }
 private:
   OBJ_PTR const m_objPtr;
   MEM_PTR m_memPtr;
@@ -202,14 +230,17 @@
  * as well as the function templates \ref MakeCallback :
  * \include samples/main-callback.cc
  */
+
 template<typename R, 
    typename T1 = empty, typename T2 = empty, 
    typename T3 = empty, typename T4 = empty,
    typename T5 = empty>
 class Callback : public CallbackBase {
 public:
+  // There are two dummy args below to ensure that this constructor is
+  // always properly disambiguited by the c++ compiler
   template <typename FUNCTOR>
-  Callback (FUNCTOR const &functor) 
+  Callback (FUNCTOR const &functor, bool, bool) 
       : m_impl (new FunctorCallbackImpl<FUNCTOR,R,T1,T2,T3,T4,T5> (functor))
   {}
 
@@ -227,25 +258,29 @@
   }
 
   Callback () : m_impl () {}
-  R operator() (void) {
+  R operator() (void) const {
       return (*(m_impl.Get ())) ();
   }
-  R operator() (T1 a1) {
+  R operator() (T1 a1) const {
       return (*(m_impl.Get ())) (a1);
   }
-  R operator() (T1 a1, T2 a2) {
+  R operator() (T1 a1, T2 a2) const {
       return (*(m_impl).Get ()) (a1,a2);
   }
-  R operator() (T1 a1, T2 a2, T3 a3) {
+  R operator() (T1 a1, T2 a2, T3 a3) const {
       return (*(m_impl).Get ()) (a1,a2,a3);
   }
-  R operator() (T1 a1, T2 a2, T3 a3, T4 a4) {
+  R operator() (T1 a1, T2 a2, T3 a3, T4 a4) const {
       return (*(m_impl).Get ()) (a1,a2,a3,a4);
   }
-  R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) {
+  R operator() (T1 a1, T2 a2, T3 a3, T4 a4,T5 a5) const {
       return (*(m_impl).Get ()) (a1,a2,a3,a4,a5);
   }
 
+  bool IsEqual (CallbackBase const &other) {
+    return PeekImpl ()->IsEqual (other.PeekImpl ());
+  }
+
   bool CheckType (CallbackBase const& other) {
     CallbackImplBase *otherBase = other.PeekImpl ();
     if (dynamic_cast<CallbackImpl<R,T1,T2,T3,T4,T5> *> (otherBase) != 0)
@@ -351,7 +386,7 @@
  */
 template <typename R>
 Callback<R> MakeCallback (R (*fnPtr) ()) {
-  return Callback<R> (fnPtr);
+  return Callback<R> (fnPtr, true, true);
 }
 /**
  * \ingroup MakeCallback
@@ -362,7 +397,7 @@
  */
 template <typename R, typename T1>
 Callback<R,T1> MakeCallback (R (*fnPtr) (T1)) {
-  return Callback<R,T1> (fnPtr);
+  return Callback<R,T1> (fnPtr, true, true);
 }
 /**
  * \ingroup MakeCallback
@@ -373,7 +408,7 @@
  */
 template <typename R, typename T1, typename T2>
 Callback<R,T1,T2> MakeCallback (R (*fnPtr) (T1,T2)) {
-  return Callback<R,T1,T2> (fnPtr);
+  return Callback<R,T1,T2> (fnPtr, true, true);
 }
 /**
  * \ingroup MakeCallback
@@ -384,7 +419,7 @@
  */
 template <typename R, typename T1, typename T2,typename T3>
 Callback<R,T1,T2,T3> MakeCallback (R (*fnPtr) (T1,T2,T3)) {
-  return Callback<R,T1,T2,T3> (fnPtr);
+  return Callback<R,T1,T2,T3> (fnPtr, true, true);
 }
 /**
  * \ingroup MakeCallback
@@ -395,7 +430,7 @@
  */
 template <typename R, typename T1, typename T2,typename T3,typename T4>
 Callback<R,T1,T2,T3,T4> MakeCallback (R (*fnPtr) (T1,T2,T3,T4)) {
-  return Callback<R,T1,T2,T3,T4> (fnPtr);
+  return Callback<R,T1,T2,T3,T4> (fnPtr, true, true);
 }
 /**
  * \ingroup MakeCallback
@@ -406,7 +441,7 @@
  */
 template <typename R, typename T1, typename T2,typename T3,typename T4,typename T5>
 Callback<R,T1,T2,T3,T4,T5> MakeCallback (R (*fnPtr) (T1,T2,T3,T4,T5)) {
-  return Callback<R,T1,T2,T3,T4,T5> (fnPtr);
+  return Callback<R,T1,T2,T3,T4,T5> (fnPtr, true, true);
 }
 
 
@@ -503,11 +538,34 @@
   R operator() (T1 a1,T2 a2,T3 a3,T4 a4,T5 a5) {
       return m_functor (m_a,a1,a2,a3,a4,a5);
   }
+  virtual bool IsEqual (CallbackImplBase const *other) const {
+    BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *otherDerived = 
+      dynamic_cast<BoundFunctorCallbackImpl<T,R,TX,T1,T2,T3,T4,T5> const *> (other);
+    if (otherDerived == 0)
+      {
+        return false;
+      }
+    else if (otherDerived->m_functor != m_functor ||
+             otherDerived->m_a != m_a)
+      {
+        return false;
+      }
+    return true;
+  }
 private:
   T m_functor;
   TX m_a;
 };
 
+template <typename R, typename TX>
+Callback<R> MakeBoundCallback (R (*fnPtr) (TX), TX a) {
+  ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> impl =
+  ReferenceList<CallbackImpl<R,empty,empty,empty,empty,empty>*> (
+  new BoundFunctorCallbackImpl<R (*) (TX),R,TX,empty,empty,empty,empty,empty> (fnPtr, a)
+  );
+  return Callback<R> (impl);
+}
+
 template <typename R, typename TX, typename T1>
 Callback<R,T1> MakeBoundCallback (R (*fnPtr) (TX,T1), TX a) {
   ReferenceList<CallbackImpl<R,T1,empty,empty,empty,empty>*> impl =
--- a/src/core/fatal-error.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/core/fatal-error.h	Sun Mar 18 14:06:51 2007 -0700
@@ -22,10 +22,9 @@
 #define FATAL_ERROR_H
 
 #include "assert.h"
-#include <iostream>
 
 /**
- * \defgroup error
+ * \defgroup error Error
  * \brief fatal error handling
  *
  * \param msg message to output when this macro is hit.
--- a/src/devices/p2p/p2p-net-device.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/p2p/p2p-net-device.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -22,6 +22,7 @@
 // Implementation of a point-to-point network device
 // George F. Riley, Georgia Tech, Spring 2007
 
+#include "ns3/empty-trace-resolver.h"
 #include "p2p-net-device.h"
 #include "p2p-channel.h"
 
@@ -60,6 +61,12 @@
   return true;
 }
 
+TraceResolver *
+P2PNetDevice::DoCreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
+
 void
 P2PNetDevice::Receive(Packet p)
 {
--- a/src/devices/p2p/p2p-net-device.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/p2p/p2p-net-device.h	Sun Mar 18 14:06:51 2007 -0700
@@ -42,6 +42,8 @@
   void TxComplete (void);
  private:
   virtual bool SendTo (Packet& p, const MacAddress& dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
+
   double m_rate;
   P2PChannel *m_channel;
 };
--- a/src/devices/serial/channel.cc	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/* -*- 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: Craig Dowell <craigdo@ee.washingon.edu>
- *
- *	Thu Feb 15 14:50:46 PST 2007 craigdo: Created.
- */
-
-#include "ns3/debug.h"
-#include "channel.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("Channel");
-
-namespace ns3 {
-
-Channel::Channel ()
-  : m_name("Channel")
-{
-  NS_DEBUG("Channel::Channel ()");
-}
-
-  Channel::Channel (std::string name)
-    : m_name(name)
-{
-  NS_DEBUG("Channel::Channel (" << name << ")");
-}
-
-Channel::~Channel ()
-{
-  NS_DEBUG("Channel::~Channel ()");
-}
-
-  void
-Channel::SetName(std::string name)
-{
-  m_name = name;
-}
-
-  std::string
-Channel::GetName(void)
-{
-  return m_name;
-}
-
-} // namespace ns3
--- a/src/devices/serial/channel.h	Sun Mar 18 19:31:32 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/* -*- 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: Craig Dowell <craigdo@ee.washingon.edu>
- *
- *      Wed Feb 14 16:05:46 PST 2007 craigdo:  Created
- */
-
-#include <list>
-#include "ns3/packet.h"
-#include "layer-connector.h"
-
-#ifndef CHANNEL_H
-#define CHANNEL_H
-
-namespace ns3 {
-
-/**
- * \brief Abstract Channel Base Class.
- *
- * A channel is a logical path over which information flows.  The path can
- * be as simple as a short piece of wire, or as complicated as space-time.
- */
-class Channel
-{
-public:
-  Channel ();
-  Channel (std::string name);
-  virtual ~Channel ();
-
-  virtual void SetName(std::string);
-  virtual std::string GetName(void);
-
-protected:
-  std::string m_name;
-
-private:
-};
-
-}; // namespace ns3
-
-#endif /* CHANNEL_H */
--- a/src/devices/serial/serial-channel.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-channel.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -21,6 +21,7 @@
 
 #include "serial-channel.h"
 #include "serial-net-device.h"
+#include "serial-phy.h"
 #include "ns3/packet.h"
 #include "ns3/simulator.h"
 #include "ns3/debug.h"
@@ -32,7 +33,8 @@
 //
 // By default, you get a channel with the name "Serial Channel" that has an
 // "infitely" fast transmission speed and zero delay.
-//
+// XXX: this does not work because m_bps = 0 results in infinitely slow transmission
+// speed. 
 SerialChannel::SerialChannel()
 : 
   Channel ("Serial Channel"), 
@@ -58,13 +60,13 @@
 }
 
   void
-SerialChannel::Attach(SerialNetDevice *device)
+SerialChannel::Attach(SerialPhy *phy)
 {
-  NS_DEBUG("SerialChannel::Attach (" << device << ")");
+  NS_DEBUG("SerialChannel::Attach (" << phy << ")");
   NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
-  NS_ASSERT(device);
+  NS_ASSERT(phy);
 
-  m_link[m_nDevices].m_src = device;
+  m_link[m_nDevices].m_src = phy;
   ++m_nDevices;
 //
 // If we have both devices connected to the channel, then finish introducing
@@ -79,8 +81,8 @@
     }
 }
 
-  void
-SerialChannel::TransmitCompleteEvent(Packet &p, SerialNetDevice *src)
+void
+SerialChannel::TransmitCompleteEvent(Packet p, SerialPhy *src)
 {
   NS_DEBUG("SerialChannel::TransmitCompleteEvent (" << &p << ", " << 
     src << ")");
@@ -97,8 +99,8 @@
   m_link[wire].m_dst->Receive (p);
 }
 
-  bool
-SerialChannel::Propagate(Packet& p, SerialNetDevice* src)
+bool
+SerialChannel::Propagate(Packet& p, SerialPhy* src)
 {
   NS_DEBUG("SerialChannel::DoPropagate (" << &p << ", " << src << ")");
 
@@ -119,19 +121,27 @@
 // I believe Raj has a method in the DataRate class to do this.  Should use
 // it when it is available.
 //
-  Time tEvent = Simulator::Now () + 
-    Seconds (static_cast<double> (p.GetSize() * 8) / 
-    static_cast<double> (m_bps)) + m_delay;
-
-  NS_DEBUG("SerialChannel::DoSend (): Schedule Receive at " << tEvent);
+  Time tEvent =  Seconds (static_cast<double> (p.GetSize() * 8) / 
+                          static_cast<double> (m_bps)) + m_delay;
 
-#if 0
+  NS_DEBUG("SerialChannel::DoSend (): Schedule Receive delay " << tEvent);
+
+  Packet packet = p;
   Simulator::Schedule (tEvent, &SerialChannel::TransmitCompleteEvent, this, 
-    p, src);
-#else
-  TransmitCompleteEvent (p, src);
-#endif
+                       p, src);
   return true;
 }
 
+uint32_t 
+SerialChannel::GetNDevices (void) const
+{
+  return m_nDevices;
+}
+NetDevice *
+SerialChannel::GetDevice (uint32_t i) const
+{
+  return m_link[i].m_src->GetDevice ();
+}
+
+
 } // namespace ns3
--- a/src/devices/serial/serial-channel.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-channel.h	Sun Mar 18 14:06:51 2007 -0700
@@ -20,8 +20,7 @@
 #define SERIAL_CHANNEL_H
 
 #include <list>
-#include "channel.h"
-#include "serial-phy.h"
+#include "ns3/channel.h"
 #include "ns3/packet.h"
 #include "ns3/nstime.h"
 
@@ -29,6 +28,8 @@
 
 // temporary until Raj's code makes it into the dev tree
 typedef uint64_t DataRate;
+class SerialPhy;
+class NetDevice;
 
 /**
  * \brief Simple Serial Channel.
@@ -60,11 +61,15 @@
   SerialChannel ();
   SerialChannel (std::string name, DataRate bps, Time delay);
 
-  void Attach (SerialNetDevice* nd);
-  bool Propagate (Packet& p, SerialNetDevice *src);
+  void Attach (SerialPhy* phy);
+  bool Propagate (Packet& p, SerialPhy *src);
 
-protected:
-  void TransmitCompleteEvent (Packet &p, SerialNetDevice *src);
+  virtual uint32_t GetNDevices (void) const;
+  virtual NetDevice *GetDevice (uint32_t i) const;
+
+
+private:
+  void TransmitCompleteEvent (Packet p, SerialPhy *src);
 
   std::string   m_name;
   DataRate      m_bps;
@@ -83,9 +88,9 @@
   {
   public:
     Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
-    WireState        m_state;    
-    SerialNetDevice *m_src;
-    SerialNetDevice *m_dst;
+    WireState        m_state;
+    SerialPhy *m_src;
+    SerialPhy *m_dst;
   };
     
   Link    m_link[N_DEVICES];
--- a/src/devices/serial/serial-net-device.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-net-device.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -23,6 +23,7 @@
 #include <cassert>
 #include "ns3/debug.h"
 #include "ns3/queue.h"
+#include "ns3/composite-trace-resolver.h"
 #include "serial-net-device.h"
 #include "serial-channel.h"
 #include "serial-phy.h"
@@ -51,10 +52,11 @@
 SerialNetDevice::~SerialNetDevice()
 {
   NS_DEBUG ("SerialNetDevice::~SerialNetDevice ()");
+  delete m_phy;
 }
 
 
-  bool
+bool
 SerialNetDevice::SendTo (Packet& p, const MacAddress& dest)
 {
   NS_DEBUG ("SerialNetDevice::SendTo (" << &p << ", " << &dest << ")");
@@ -74,12 +76,23 @@
     return false;
 }
 
-  bool
+TraceResolver *
+SerialNetDevice::DoCreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("queue", 
+                 MakeCallback (&Queue::CreateTraceResolver, m_queue),
+                 SerialNetDevice::QUEUE);
+  return resolver;
+}
+
+bool
 SerialNetDevice::Attach (SerialChannel* ch)
 {
   NS_DEBUG ("SerialNetDevice::Attach (" << &ch << ")");
 
   m_channel = ch;
+  m_phy->Attach (m_channel);
   /* 
    * For now, this device is up whenever a channel is attached to it.
    * In fact, it should become up only when the second device
@@ -106,8 +119,7 @@
   // ignore return value for now.
   NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
 
-  // Dispatch this to SerialPhy::Receive
-  m_phy->Receive (p);
+  ForwardUp (p);
 }
 
 void
@@ -125,7 +137,7 @@
       // send packet to address tag.address
 #endif
       NS_DEBUG ("SerialNetDevice::NotifyDataAvailable (): Dequeued");
-      m_channel->Propagate(p, this);
+      m_phy->Send(p);
     }
 }
 
--- a/src/devices/serial/serial-net-device.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-net-device.h	Sun Mar 18 14:06:51 2007 -0700
@@ -35,8 +35,10 @@
 class Queue;
 
 class SerialNetDevice : public NetDevice {
-friend class SerialPhy;
 public:
+  enum TraceType {
+    QUEUE,
+  };
   SerialNetDevice(Node* node, const MacAddress& addr);
   virtual ~SerialNetDevice();
 
@@ -48,7 +50,7 @@
 public:
   bool Attach(SerialChannel* ch);
   void AddQueue(Queue *);
-  // called by ChannelSerial
+  // called by SerialPhy
   void Receive (Packet& p);
 
 protected:
@@ -58,6 +60,7 @@
 private:
   virtual void NotifyDataAvailable (void);
   virtual bool SendTo (Packet& p, const MacAddress& dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
 
   SerialPhy* m_phy;
   SerialChannel* m_channel;
--- a/src/devices/serial/serial-phy.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-phy.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -40,30 +40,31 @@
   NS_DEBUG ("SerialPhy::~SerialPhy ()");
 }
 
-void
-SerialPhy::NotifyDataAvailable(void)
+void 
+SerialPhy::Send (Packet &p)
 {
-  NS_DEBUG ("SerialPhy::NotifyDataAvailable ()");
+  m_channel->Propagate (p, this);
+}
+void 
+SerialPhy::Attach (SerialChannel *channel)
+{
+  m_channel = channel;
+  m_channel->Attach (this);
+}
 
-  Packet p;
-  bool found = m_netdevice->GetQueue ()->Dequeue (p);
-  if (found)
-    {
-#ifdef NOTYET
-      struct NetDevicePacketDestAddress tag;
-      p.PeekTag (tag);
-      // send packet to address tag.address
-#endif
-      NS_DEBUG ("SerialPhy::NotifyDataAvailable (): Dequeued");
-      m_netdevice->GetChannel()->Propagate(p, m_netdevice);
-    }
+SerialNetDevice *
+SerialPhy::GetDevice (void)
+{
+  return m_netdevice;
 }
 
+
+
 void
 SerialPhy::Receive (Packet& p)
 {
   NS_DEBUG ("SerialPhy::Receive (" << &p << ")");
-  m_netdevice->ForwardUp (p);
+  m_netdevice->Receive (p);
 }
 
 } // namespace ns3
--- a/src/devices/serial/serial-phy.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/devices/serial/serial-phy.h	Sun Mar 18 14:06:51 2007 -0700
@@ -21,22 +21,27 @@
 #ifndef SERIAL_PHY_H
 #define SERIAL_PHY_H
 
-#include <string.h>
-#include "ns3/internet-node.h"
-#include "ns3/packet.h"
-#include "serial-net-device.h"
+namespace ns3 {
 
-namespace ns3 {
+class SerialNetDevice;
+class SerialChannel;
+class Node;
+class Packet;
 
 class SerialPhy {
 public:
   SerialPhy(Node* node, SerialNetDevice* netdevice);
   virtual ~SerialPhy();
-  virtual void NotifyDataAvailable (void);
+
+  void Send (Packet &p);
   void Receive (Packet& p);
+  void Attach (SerialChannel *channel);
+
+  SerialNetDevice *GetDevice (void);
 
 private:
   Node* m_node;
+  SerialChannel *m_channel;
   SerialNetDevice* m_netdevice;
 };
 
--- a/src/node/arp-ipv4-interface.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/arp-ipv4-interface.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -21,6 +21,7 @@
  */
 
 #include "ns3/packet.h"
+#include "ns3/composite-trace-resolver.h"
 
 #include "arp-ipv4-interface.h"
 #include "arp.h"
@@ -37,6 +38,20 @@
 ArpIpv4Interface::~ArpIpv4Interface ()
 {}
 
+TraceResolver *
+ArpIpv4Interface::DoCreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  if (GetDevice () != 0)
+    {
+      resolver->Add ("netdevice",
+                     MakeCallback (&NetDevice::CreateTraceResolver, GetDevice ()),
+                     ArpIpv4Interface::NETDEVICE);
+    }
+  
+  return resolver;
+}
+
 void 
 ArpIpv4Interface::SendTo (Packet p, Ipv4Address dest)
 {
--- a/src/node/arp-ipv4-interface.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/arp-ipv4-interface.h	Sun Mar 18 14:06:51 2007 -0700
@@ -31,11 +31,16 @@
 class ArpIpv4Interface : public Ipv4Interface
 {
  public:
+  enum TraceType {
+    NETDEVICE,
+    ARP,
+  };
   ArpIpv4Interface (Node *node, NetDevice *device);
   virtual ~ArpIpv4Interface ();
 
  private:
   virtual void SendTo (Packet p, Ipv4Address dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
   Node *m_node;
 };
 
--- a/src/node/arp.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/arp.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -20,6 +20,7 @@
  */
 #include "ns3/packet.h"
 #include "ns3/debug.h"
+#include "ns3/empty-trace-resolver.h"
 #include "arp.h"
 #include "arp-header.h"
 #include "arp-cache.h"
@@ -53,6 +54,12 @@
   return new Arp (node);
 }
 
+TraceResolver *
+Arp::CreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
+
 ArpCache *
 Arp::FindCache (NetDevice *device)
 {
--- a/src/node/arp.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/arp.h	Sun Mar 18 14:06:51 2007 -0700
@@ -32,6 +32,8 @@
 class NetDevice;
 class Node;
 class Packet;
+class TraceResolver;
+class TraceContext;
 
 class Arp : public L3Protocol
 {
@@ -42,6 +44,8 @@
   ~Arp ();
   virtual Arp *Copy (Node *node) const;
 
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
+
   virtual void Receive(Packet& p, NetDevice &device);
   bool Lookup (Packet &p, Ipv4Address destination, 
 	       NetDevice *device,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/channel.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,59 @@
+/* -*- 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: Craig Dowell <craigdo@ee.washingon.edu>
+ *
+ *	Thu Feb 15 14:50:46 PST 2007 craigdo: Created.
+ */
+
+#include "ns3/debug.h"
+#include "channel.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("Channel");
+
+namespace ns3 {
+
+Channel::Channel ()
+  : m_name("Channel")
+{
+  NS_DEBUG("Channel::Channel ()");
+}
+
+Channel::Channel (std::string name)
+  : m_name(name)
+{
+  NS_DEBUG("Channel::Channel (" << name << ")");
+}
+
+Channel::~Channel ()
+{
+  NS_DEBUG("Channel::~Channel ()");
+}
+
+  void
+Channel::SetName(std::string name)
+{
+  m_name = name;
+}
+
+  std::string
+Channel::GetName(void)
+{
+  return m_name;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/channel.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,59 @@
+/* -*- 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: Craig Dowell <craigdo@ee.washingon.edu>
+ *
+ *      Wed Feb 14 16:05:46 PST 2007 craigdo:  Created
+ */
+#ifndef CHANNEL_H
+#define CHANNEL_H
+
+#include <string>
+#include <stdint.h>
+
+namespace ns3 {
+
+class NetDevice;
+
+/**
+ * \brief Abstract Channel Base Class.
+ *
+ * A channel is a logical path over which information flows.  The path can
+ * be as simple as a short piece of wire, or as complicated as space-time.
+ */
+class Channel
+{
+public:
+  Channel ();
+  Channel (std::string name);
+  virtual ~Channel ();
+
+  void SetName(std::string);
+  std::string GetName(void);
+
+  virtual uint32_t GetNDevices (void) const = 0;
+  virtual NetDevice *GetDevice (uint32_t i) const = 0;
+
+protected:
+  std::string m_name;
+
+private:
+};
+
+}; // namespace ns3
+
+#endif /* CHANNEL_H */
--- a/src/node/drop-tail.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/drop-tail.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -25,34 +25,19 @@
 namespace ns3 {
 
 DropTailQueue::DropTailQueue () :
-  Queue (""),
+  Queue (),
   m_packets (),
   m_maxPackets(DTQ_NPACKETS_MAX_DEFAULT)
 {
   NS_DEBUG("DropTailQueue::DropTailQueue ()");
 }
 
-
-DropTailQueue::DropTailQueue (std::string const&name)
-  : Queue (name),
-    m_packets(),
-    m_maxPackets(DTQ_NPACKETS_MAX_DEFAULT)
-{
-  NS_DEBUG("DropTailQueue::DropTailQueue");
-}
-
 DropTailQueue::~DropTailQueue ()
 {
   NS_DEBUG("DropTailQueue::~DropTailQueue ()");
 }
 
 void 
-DropTailQueue::RegisterTraces (TraceContainer &traceContainer)
-{
-  Queue::QueueRegisterTraces (traceContainer);
-}
-
-  void 
 DropTailQueue::SetMaxPackets (uint32_t npackets)
 {
   NS_DEBUG("DropTailQueue::SetMaxPackets (" << npackets << ")");
@@ -60,7 +45,7 @@
   m_maxPackets = npackets;
 }
 
-  uint32_t 
+uint32_t 
 DropTailQueue::GetMaxPackets (void)
 {
   NS_DEBUG("DropTailQueue::GetMaxPackets () <= " << m_maxPackets);
@@ -68,12 +53,12 @@
   return m_maxPackets;
 }
 
-  bool 
+bool 
 DropTailQueue::DoEnqueue (const Packet& p)
 {
   NS_DEBUG("DropTailQueue::DoEnqueue (" << &p << ")");
 
-  if (GetNPackets () >= m_maxPackets)
+  if (m_packets.size () >= m_maxPackets)
     {
       NS_DEBUG("DropTailQueue::DoEnqueue (): Queue full -- droppping pkt");
       Drop (p);
@@ -84,7 +69,7 @@
   return true;
 }
 
-  bool
+bool
 DropTailQueue::DoDequeue (Packet& p)
 {
   NS_DEBUG("DropTailQueue::DoDequeue (" << &p << ")");
--- a/src/node/drop-tail.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/drop-tail.h	Sun Mar 18 14:06:51 2007 -0700
@@ -33,9 +33,6 @@
 class DropTailQueue : public Queue {
 public:
   DropTailQueue ();
-  DropTailQueue (std::string const &name);
-
-  void RegisterTraces (TraceContainer &traceContainer);
 
   virtual ~DropTailQueue();
 
--- a/src/node/internet-node.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/internet-node.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -21,6 +21,8 @@
 // Implementation of the InternetNode class for ns3.
 // George F. Riley, Georgia Tech, Fall 2006
 
+#include "ns3/composite-trace-resolver.h"
+
 #include "net-device-list.h"
 #include "l3-demux.h"
 #include "ipv4-l4-demux.h"
@@ -96,6 +98,22 @@
    return copy;
 }
 
+TraceResolver *
+InternetNode::CreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("ipv4",
+                 MakeCallback (&Ipv4::CreateTraceResolver, GetIpv4 ()),
+                 InternetNode::IPV4);
+  resolver->Add ("arp",
+                 MakeCallback (&Arp::CreateTraceResolver, GetArp ()),
+                 InternetNode::ARP);
+  resolver->Add ("udp",
+                 MakeCallback (&Udp::CreateTraceResolver, GetUdp ()),
+                 InternetNode::UDP);
+  return resolver;
+}
+
 
 NetDeviceList*   
 InternetNode::GetNetDeviceList() const
--- a/src/node/internet-node.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/internet-node.h	Sun Mar 18 14:06:51 2007 -0700
@@ -35,11 +35,17 @@
 class InternetNode : public Node 
 {
 public:
+  enum TraceType {
+    IPV4,
+    UDP,
+    ARP,
+  };
   InternetNode();
   InternetNode(const InternetNode&);
   InternetNode const &operator = (InternetNode const &o);
   virtual ~InternetNode ();
   virtual InternetNode* Copy() const;
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
   // Capability access
   virtual NetDeviceList*   GetNetDeviceList() const;
   virtual L3Demux*         GetL3Demux() const;
--- a/src/node/ipv4-interface.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-interface.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -45,6 +45,12 @@
   return m_netdevice;
 }
 
+TraceResolver *
+Ipv4Interface::CreateTraceResolver (TraceContext const &context)
+{
+  return DoCreateTraceResolver (context);
+}
+
 void 
 Ipv4Interface::SetAddress (Ipv4Address a)
 {
--- a/src/node/ipv4-interface.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-interface.h	Sun Mar 18 14:06:51 2007 -0700
@@ -30,6 +30,8 @@
 
 class NetDevice;
 class Packet;
+class TraceResolver;
+class TraceContext;
 
 /**
  * \brief The IPv4 representation of a network interface
@@ -62,6 +64,7 @@
   Ipv4Interface (NetDevice *nd);
   virtual ~Ipv4Interface();
 
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
   NetDevice *GetDevice (void) const;
 
   void SetAddress (Ipv4Address a);
@@ -96,6 +99,7 @@
 
  private:
   virtual void SendTo (Packet p, Ipv4Address dest) = 0;
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
   NetDevice* m_netdevice;
   bool m_ifup;
   Ipv4Address m_address;
--- a/src/node/ipv4-l4-demux.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-l4-demux.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -22,6 +22,8 @@
 // Define the layer 4 demultiplexer object for ns3.
 // George F. Riley, Georgia Tech, Fall 2006
 
+#include <sstream>
+#include "ns3/composite-trace-resolver.h"
 #include "ipv4-l4-demux.h"
 #include "ipv4-l4-protocol.h"
 
@@ -48,6 +50,23 @@
     }
   return copy;
 }
+TraceResolver *
+Ipv4L4Demux::CreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+    {
+      Ipv4L4Protocol *protocol = *i;
+      std::string protValue;
+      std::ostringstream oss (protValue);
+      oss << (*i)->GetProtocolNumber ();
+      Ipv4L4ProtocolTraceType protocolNumber = (*i)->GetProtocolNumber ();
+      resolver->Add (protValue,
+                     MakeCallback (&Ipv4L4Protocol::CreateTraceResolver, protocol),
+                     protocolNumber);
+    }
+  return resolver;
+}
 Ipv4L4Protocol* 
 Ipv4L4Demux::Insert(const Ipv4L4Protocol&protocol)
 {
--- a/src/node/ipv4-l4-demux.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-l4-demux.h	Sun Mar 18 14:06:51 2007 -0700
@@ -32,12 +32,16 @@
 
 class Ipv4L4Protocol;
 class Node;
+class TraceResolver;
+class TraceContext;
 
 class Ipv4L4Demux {
 public:
+  typedef int Ipv4L4ProtocolTraceType;
   Ipv4L4Demux (Node *node);
   virtual ~Ipv4L4Demux();
   Ipv4L4Demux* Copy(Node *node) const;
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
   Ipv4L4Protocol* Insert(const Ipv4L4Protocol&);
   Ipv4L4Protocol* Lookup(int protocolNumber);
   void        Erase(Ipv4L4Protocol*);
--- a/src/node/ipv4-l4-protocol.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-l4-protocol.h	Sun Mar 18 14:06:51 2007 -0700
@@ -31,6 +31,8 @@
 class Node;
 class Packet;
 class Ipv4Address;
+class TraceResolver;
+class TraceContext;
   
 class Ipv4L4Protocol {
 public:
@@ -41,6 +43,7 @@
   int GetVersion() const;
 
   virtual Ipv4L4Protocol* Copy(Node *node) const = 0;
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
   /**
    * Called from lower-level layers to send the packet up
    * in the stack. 
--- a/src/node/ipv4-loopback-interface.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-loopback-interface.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -19,6 +19,7 @@
  * Authors: 
  *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
  */
+#include "ns3/empty-trace-resolver.h"
 #include "ipv4-loopback-interface.h"
 #include "net-device.h"
 #include "node.h"
@@ -33,6 +34,7 @@
   Node *PeekNode (void) const;
 private:
   virtual bool SendTo (Packet& p, const MacAddress& dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
 };
 
 Ipv4DummyNetDevice::Ipv4DummyNetDevice (Node *node)
@@ -50,6 +52,11 @@
 {
   return false;
 }
+TraceResolver *
+Ipv4DummyNetDevice::DoCreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
 
 
 Ipv4LoopbackInterface::Ipv4LoopbackInterface (Node *node)
@@ -68,6 +75,12 @@
   return m_node;
 }
 
+TraceResolver *
+Ipv4LoopbackInterface::DoCreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
+
 void 
 Ipv4LoopbackInterface::SendTo (Packet packet, Ipv4Address dest)
 {
--- a/src/node/ipv4-loopback-interface.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4-loopback-interface.h	Sun Mar 18 14:06:51 2007 -0700
@@ -36,6 +36,7 @@
 
  private:
   virtual void SendTo (Packet p, Ipv4Address dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
   Node *GetNode (void) const;
 
   Node *m_node;
--- a/src/node/ipv4.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -21,6 +21,9 @@
 
 #include "ns3/packet.h"
 #include "ns3/debug.h"
+#include "ns3/composite-trace-resolver.h"
+#include "ns3/array-trace-resolver.h"
+#include "ns3/callback.h"
 
 #include "ipv4.h"
 #include "ipv4-l4-protocol.h"
@@ -68,6 +71,30 @@
   delete m_defaultRoute;
 }
 
+TraceResolver *
+Ipv4::CreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("tx", m_txTrace, Ipv4::TX);
+  resolver->Add ("rx", m_rxTrace, Ipv4::RX);
+  resolver->Add ("drop", m_dropTrace, Ipv4::DROP);
+  resolver->Add ("interfaces", 
+                 MakeCallback (&Ipv4::InterfacesCreateTraceResolver, this), 
+                 Ipv4::INTERFACES);
+  return resolver;
+}
+
+TraceResolver *
+Ipv4::InterfacesCreateTraceResolver (TraceContext const &context)
+{
+  ArrayTraceResolver<Ipv4Interface> *resolver = 
+    new ArrayTraceResolver<Ipv4Interface> 
+    (context,
+     MakeCallback (&Ipv4::GetNInterfaces, this),
+     MakeCallback (&Ipv4::GetInterface, this));
+  return resolver;
+}
+
 void 
 Ipv4::SetDefaultTtl (uint8_t ttl)
 {
@@ -77,8 +104,8 @@
 
 void 
 Ipv4::AddHostRouteTo (Ipv4Address dest, 
-				Ipv4Address nextHop, 
-				uint32_t interface)
+                      Ipv4Address nextHop, 
+                      uint32_t interface)
 {
   Ipv4Route *route = new Ipv4Route ();
   *route = Ipv4Route::CreateHostRouteTo (dest, nextHop, interface);
@@ -281,7 +308,7 @@
   return 0;
 }
 uint32_t 
-Ipv4::GetNInterfaces (void) const
+Ipv4::GetNInterfaces (void)
 {
   return m_nInterfaces;
 }
@@ -309,7 +336,7 @@
 void 
 Ipv4::Receive(Packet& packet, NetDevice &device)
 {
-  // XXX trace here.
+  m_rxTrace (packet);
   Ipv4Header ipHeader;
   packet.Peek (ipHeader);
   packet.Remove (ipHeader);
@@ -357,6 +384,7 @@
   if (route == 0) 
     {
       NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
+      m_dropTrace (packet);
       return;
     }
 
@@ -370,7 +398,7 @@
   packet.Add (ip);
   Ipv4Interface *outInterface = GetInterface (route.GetInterface ());
   NS_ASSERT (packet.GetSize () <= outInterface->GetMtu ());
-  // XXX log trace here.
+  m_txTrace (packet);
   if (route.IsGateway ()) 
     {
       outInterface->Send (packet, route.GetGateway ());
@@ -425,6 +453,7 @@
       // Should send ttl expired here
       // XXX
       NS_DEBUG ("not for me -- ttl expired. drop.");
+      m_dropTrace (packet);
       return true;
     }
   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
@@ -432,6 +461,7 @@
   if (route == 0) 
     {
       NS_DEBUG ("not for me -- forwarding but no route to host. drop.");
+      m_dropTrace (packet);
       return true;
     }
   NS_DEBUG ("not for me -- forwarding.");
--- a/src/node/ipv4.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/ipv4.h	Sun Mar 18 14:06:51 2007 -0700
@@ -24,6 +24,8 @@
 
 #include <list>
 #include <stdint.h>
+#include "ns3/callback-trace-source.h"
+#include "ns3/array-trace-resolver.h"
 #include "ipv4-address.h"
 #include "l3-protocol.h"
 
@@ -36,6 +38,8 @@
 class Ipv4Header;
 class Ipv4Route;
 class Node;
+class TraceResolver;
+class TraceContext;
 
 
 /**
@@ -46,9 +50,19 @@
 public:
   static const uint16_t PROT_NUMBER;
 
+  enum TraceType {
+    TX,
+    RX,
+    DROP,
+    INTERFACES,
+  };
+  typedef ArrayTraceResolver<Ipv4Interface>::Index InterfaceIndex;
+
   Ipv4(Node *node);
   virtual ~Ipv4 ();
 
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
+
   void SetDefaultTtl (uint8_t ttl);
     
   /* add route to host dest through host nextHop 
@@ -88,7 +102,7 @@
   
   uint32_t AddInterface (Ipv4Interface *interface);
   Ipv4Interface * GetInterface (uint32_t i);
-  uint32_t GetNInterfaces (void) const;
+  uint32_t GetNInterfaces (void);
   Ipv4Interface *FindInterfaceForDevice (NetDevice const*device);
   
 
@@ -109,6 +123,7 @@
   void SendRealOut (Packet const &packet, Ipv4Header const &ip, Ipv4Route const &route);
   bool Forwarding (Packet const &packet, Ipv4Header &ipHeader, NetDevice &device);
   void ForwardUp (Packet p, Ipv4Header const&ip);
+  TraceResolver *InterfacesCreateTraceResolver (TraceContext const &context);
 
   typedef std::list<Ipv4Interface*> Ipv4InterfaceList;
   typedef std::list<Ipv4Route *> HostRoutes;
@@ -126,6 +141,9 @@
   NetworkRoutes m_networkRoutes;
   Ipv4Route *m_defaultRoute;
   Node *m_node;
+  CallbackTraceSource<Packet const &> m_txTrace;
+  CallbackTraceSource<Packet const &> m_rxTrace;
+  CallbackTraceSource<Packet const &> m_dropTrace;
 };
 
 } // Namespace ns3
--- a/src/node/l3-demux.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/l3-demux.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -20,7 +20,9 @@
 //
 // Implement the L3Protocols capability for ns3.
 // George F. Riley, Georgia Tech, Fall 2006
-
+#include <sstream>
+#include <string>
+#include "ns3/composite-trace-resolver.h"
 #include "l3-demux.h"
 #include "l3-protocol.h"
 
@@ -37,6 +39,23 @@
       delete i->second;
     }
 }
+
+TraceResolver *
+L3Demux::CreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  for (L3Map_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
+    {
+      std::string protValue;
+      std::ostringstream oss (protValue);
+      oss << (i->second)->GetProtocolNumber ();
+      ProtocolTraceType context = (i->second)->GetProtocolNumber ();
+      resolver->Add (protValue, 
+                     MakeCallback (&L3Protocol::CreateTraceResolver, i->second),
+                     context);
+    }
+  return resolver;
+}
   
 L3Demux* L3Demux::Copy(Node *node) const
 {
--- a/src/node/l3-demux.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/l3-demux.h	Sun Mar 18 14:06:51 2007 -0700
@@ -33,14 +33,19 @@
 
 class L3Protocol;
 class Node;
+class TraceResolver;
+class TraceContext;
 
 class L3Demux
 {
 public:
+  typedef int ProtocolTraceType;
   L3Demux(Node *node);
   virtual ~L3Demux();
   L3Demux* Copy(Node *node) const;
 
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
+
   // Insert a new protocol
   ns3::L3Protocol* Insert(const ns3::L3Protocol&);
   // Look up a protocol by protocol number
--- a/src/node/l3-protocol.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/l3-protocol.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -33,7 +33,7 @@
 {}
 L3Protocol::~L3Protocol ()
 {}
-    
+
 int 
 L3Protocol::GetProtocolNumber (void) const
 {
--- a/src/node/l3-protocol.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/l3-protocol.h	Sun Mar 18 14:06:51 2007 -0700
@@ -30,7 +30,8 @@
 class Packet;
 class NetDevice;
 class Node;
-
+class TraceResolver;
+class TraceContext;
 
 /**
  * ::Send is always defined in subclasses.
@@ -44,6 +45,8 @@
   int GetVersion() const;
 
   virtual L3Protocol* Copy(Node *node) const = 0;
+
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
   /**
    * Lower layer calls this method after calling L3Demux::Lookup
    * The ARP subclass needs to know from which NetDevice this
--- a/src/node/net-device.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/net-device.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -163,6 +163,11 @@
     }
 }
 
+TraceResolver *
+NetDevice::CreateTraceResolver (TraceContext const &context)
+{
+  return DoCreateTraceResolver (context);
+}
 
 // Receive packet from below
 bool
--- a/src/node/net-device.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/net-device.h	Sun Mar 18 14:06:51 2007 -0700
@@ -31,6 +31,8 @@
 
 class Ipv4L4Demux;
 class Node;
+class TraceResolver;
+class TraceContext;
 
 /**
  * \brief Network layer to device interface
@@ -58,6 +60,9 @@
    */
   NetDevice(Node* node, const MacAddress& addr);
   virtual ~NetDevice() {}
+
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
+
   /**
    * \return the current MacAddress of this interface.
    */
@@ -204,6 +209,7 @@
    * MUST override this method.
    */
   virtual bool SendTo (Packet& p, const MacAddress& dest) = 0;
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context) = 0;
   Node*         m_node;
   std::string   m_name;
   uint16_t      m_ifIndex;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/node-list.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,79 @@
+/* -*- 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
+ *
+ * Authors: 
+ *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+
+#include "ns3/array-trace-resolver.h"
+#include "ns3/trace-root.h"
+#include "node-list.h"
+#include "node.h"
+
+namespace ns3 {
+
+void 
+NodeList::Add (Node *node)
+{
+  GetNodes ()->push_back (node);
+}
+NodeList::Iterator 
+NodeList::Begin (void)
+{
+  return GetNodes ()->begin ();
+}
+NodeList::Iterator 
+NodeList::End (void)
+{
+  return GetNodes ()->end ();
+}
+
+std::vector<Node *> *
+NodeList::GetNodes (void)
+{
+  static bool firstTime = true;
+  if (firstTime)
+    {
+      TraceRoot::Register ("nodes", MakeCallback (&NodeList::CreateTraceResolver));
+    }
+  static std::vector<Node *> nodes;
+  return &nodes;
+}
+uint32_t 
+NodeList::GetNNodes (void)
+{
+  return GetNodes ()->size ();
+}
+Node *
+NodeList::GetNode (uint32_t n)
+{
+  return (*GetNodes ())[n];
+}
+
+TraceResolver *
+NodeList::CreateTraceResolver (TraceContext const &context)
+{
+  ArrayTraceResolver<Node> *resolver =
+    new ArrayTraceResolver<Node>
+    (context, 
+     MakeCallback (&NodeList::GetNNodes),
+     MakeCallback (&NodeList::GetNode));
+  return resolver;
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/node-list.h	Sun Mar 18 14:06:51 2007 -0700
@@ -0,0 +1,58 @@
+/* -*- 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
+ *
+ * Authors: 
+ *  Mathieu Lacage <mathieu.lacage@sophia.inria.fr>,
+ */
+#ifndef NODE_LIST_H
+#define NODE_LIST_H
+
+#include <vector>
+#include <string>
+#include "ns3/array-trace-resolver.h"
+
+namespace ns3 {
+
+class Node;
+class CallbackBase;
+class TraceResolver;
+class TraceContext;
+
+class NodeList
+{
+public:
+  typedef ArrayTraceResolver<Node>::Index NodeIndex;
+  typedef std::vector<Node *>::iterator Iterator;
+
+  static void Add (Node *node);
+  static Iterator Begin (void);
+  static Iterator End (void);
+  static TraceResolver *CreateTraceResolver (TraceContext const &context);
+
+  static Node *GetNode (uint32_t n);
+
+private:
+  static std::vector<Node *> *GetNodes (void);
+  static uint32_t GetNNodes (void);
+  
+};
+
+}//namespace ns3
+
+
+#endif /* NODE_LIST_H */
--- a/src/node/node.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/node.h	Sun Mar 18 14:06:51 2007 -0700
@@ -99,6 +99,8 @@
 class Ipv4;
 class Udp;
 class Arp;
+class TraceContext;
+class TraceResolver;
 
 class Node {
 public:
@@ -107,6 +109,8 @@
   virtual ~Node();
   virtual Node* Copy() const = 0;// Make a copy of this node
 
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context) = 0;
+
   uint32_t GetId (void) const;
   uint32_t GetSystemId (void) const;
   void SetSystemId(uint32_t s);
--- a/src/node/queue.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/queue.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -18,20 +18,20 @@
  */
 
 #include "ns3/debug.h"
+#include "ns3/composite-trace-resolver.h"
 #include "queue.h"
 
 NS_DEBUG_COMPONENT_DEFINE ("Queue");
 
 namespace ns3 {
 
-  Queue::Queue(std::string const &name) : 
+Queue::Queue() : 
   m_nBytes(0), 
   m_nTotalReceivedBytes(0),
   m_nPackets(0), 
   m_nTotalReceivedPackets(0),
   m_nTotalDroppedBytes(0),
-  m_nTotalDroppedPackets(0),
-  m_name (name)
+  m_nTotalDroppedPackets(0)
 {
   NS_DEBUG("Queue::Queue ()");
 }
@@ -41,6 +41,16 @@
   NS_DEBUG("Queue::~Queue ()");
 }
 
+TraceResolver *
+Queue::CreateTraceResolver (TraceContext const &context)
+{
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("enqueue", m_traceEnqueue, Queue::ENQUEUE);
+  resolver->Add ("dequeue", m_traceDequeue, Queue::DEQUEUE);
+  resolver->Add ("drop", m_traceDrop, Queue::DROP);
+  return resolver;
+}
+
 bool 
 Queue::Enqueue (const Packet& p)
 {
@@ -48,7 +58,7 @@
 
   NS_DEBUG("Queue::Enqueue (): m_traceEnqueue (p)");
 
-  m_traceEnqueue (m_name, p);
+  m_traceEnqueue (p);
 
   bool retval = DoEnqueue (p);
   if (retval)
@@ -77,7 +87,7 @@
       NS_DEBUG("Queue::Dequeue (): m_traceDequeue (p)");
 
       const Packet packet = p;
-      m_traceDequeue (m_name, packet);
+      m_traceDequeue (packet);
     }
 
   return retval;
@@ -115,19 +125,6 @@
   return m_nPackets == 0;
 }
 
-void
-Queue::QueueRegisterTraces (TraceContainer &container)
-{
-  NS_DEBUG("Queue::RegisterTraces (" << &container << ")");
-
-  container.RegisterCallback ("Queue::Enqueue",
-                              &m_traceEnqueue);
-  container.RegisterCallback ("Queue::Dequeue",
-                              &m_traceDequeue);
-  container.RegisterCallback ("Queue::Drop",
-                              &m_traceDrop);
-}
-
 uint32_t
 Queue::GetTotalReceivedBytes (void)
 {
@@ -182,7 +179,7 @@
   m_nTotalDroppedBytes += p.GetSize ();
 
   NS_DEBUG("Queue::Drop (): m_traceDrop (p)");
-  m_traceDrop (m_name, p);
+  m_traceDrop (p);
 }
 
 }; // namespace ns3
--- a/src/node/queue.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/queue.h	Sun Mar 18 14:06:51 2007 -0700
@@ -27,17 +27,25 @@
 
 #include <string>
 #include "ns3/packet.h"
-#include "ns3/callback-tracer.h"
-#include "ns3/trace-container.h"
+#include "ns3/callback-trace-source.h"
+#include "ns3/trace-resolver.h"
 
 namespace ns3 {
 
 class Queue
 {
 public:
-  Queue (std::string const &name);
+  enum TraceType {
+    ENQUEUE,
+    DEQUEUE,
+    DROP,
+  };
+  Queue ();
   virtual ~Queue ();
 
+  TraceResolver *CreateTraceResolver (TraceContext const &context);
+
+  bool IsEmpty (void);
   bool Enqueue (const Packet& p);
   bool Dequeue (Packet &p);
 
@@ -45,8 +53,6 @@
   uint32_t GetNPackets (void);
   uint32_t GetNBytes (void);
 
-  bool IsEmpty (void);
-
   uint32_t GetTotalReceivedBytes (void);
   uint32_t GetTotalReceivedPackets (void);
   uint32_t GetTotalDroppedBytes (void);
@@ -85,12 +91,11 @@
 protected:
   // called by subclasses to notify parent of packet drops.
   void Drop (const Packet& p);
-  void QueueRegisterTraces (TraceContainer &container);
 
 private:
-  CallbackTracer<std::string const &, const Packet &> m_traceEnqueue;
-  CallbackTracer<std::string const &, const Packet &> m_traceDequeue;
-  CallbackTracer<std::string const &, const Packet &> m_traceDrop;
+  CallbackTraceSource<const Packet &> m_traceEnqueue;
+  CallbackTraceSource<const Packet &> m_traceDequeue;
+  CallbackTraceSource<const Packet &> m_traceDrop;
 
   uint32_t m_nBytes;
   uint32_t m_nTotalReceivedBytes;
@@ -99,9 +104,6 @@
   uint32_t m_nTotalDroppedBytes;
   uint32_t m_nTotalDroppedPackets;
 
-  std::string m_name;
-
-
 #if 0
   // Static methods to manage queue default
   // Set desired queue default
--- a/src/node/udp.cc	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/udp.cc	Sun Mar 18 14:06:51 2007 -0700
@@ -21,6 +21,8 @@
 
 #include "ns3/assert.h"
 #include "ns3/packet.h"
+#include "ns3/empty-trace-resolver.h"
+
 #include "udp.h"
 #include "udp-header.h"
 #include "ipv4-end-point-demux.h"
@@ -46,6 +48,12 @@
   delete m_endPoints;
 }
 
+TraceResolver *
+Udp::CreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
+
 UdpEndPoint *
 Udp::Allocate (void)
 {
--- a/src/node/udp.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/node/udp.h	Sun Mar 18 14:06:51 2007 -0700
@@ -33,6 +33,8 @@
 namespace ns3 {
 
 class Node;
+class TraceResolver;
+class TraceContext;
 
 class Udp : public Ipv4L4Protocol {
 public:
@@ -41,6 +43,8 @@
   Udp (Node *node);
   virtual ~Udp ();
 
+  virtual TraceResolver *CreateTraceResolver (TraceContext const &context);
+
   UdpEndPoint *Allocate (void);
   UdpEndPoint *Allocate (Ipv4Address address);
   UdpEndPoint *Allocate (uint16_t port);
--- a/src/simulator/simulator.h	Sun Mar 18 19:31:32 2007 +0100
+++ b/src/simulator/simulator.h	Sun Mar 18 14:06:51 2007 -0700
@@ -151,11 +151,11 @@
   static void StopAt (Time const &time);
 
   /**
-   * Schedule an event to expire when time is reached.
-   * When the event expires, the input method will be invoked
-   * on the input object.
+   * Schedule an event to expire when the time "now + time" 
+   * is reached. When the event expires, the input method 
+   * will be invoked on the input object.
    *
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @returns an id for the scheduled event.
@@ -163,7 +163,7 @@
   template <typename T>
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (void), T *obj);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
@@ -172,7 +172,7 @@
   template <typename T, typename T1>
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1), T* obj, T1 a1);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
@@ -182,7 +182,7 @@
   template <typename T, typename T1, typename T2>
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2), T* obj, T1 a1, T2 a2);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
@@ -193,7 +193,7 @@
   template <typename T, typename T1, typename T2, typename T3>
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3), T* obj, T1 a1, T2 a2, T3 a3);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
@@ -205,7 +205,7 @@
   template <typename T, typename T1, typename T2, typename T3, typename T4>
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4), T* obj, T1 a1, T2 a2, T3 a3, T4 a4);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param mem_ptr member method pointer to invoke
    * @param obj the object on which to invoke the member method
    * @param a1 the first argument to pass to the invoked method
@@ -219,13 +219,13 @@
   static EventId Schedule (Time const &time, void (T::*mem_ptr) (T1,T2,T3,T4,T5), T* obj, 
   						 T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @returns an id for the scheduled event.
    */
   static EventId Schedule (Time const &time, void (*f) (void));
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @returns an id for the scheduled event.
@@ -233,7 +233,7 @@
   template <typename T1>
   static EventId Schedule (Time const &time, void (*f) (T1), T1 a1);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
@@ -242,7 +242,7 @@
   template <typename T1, typename T2>
   static EventId Schedule (Time const &time, void (*f) (T1,T2), T1 a1, T2 a2);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
@@ -252,7 +252,7 @@
   template <typename T1, typename T2, typename T3>
   static EventId Schedule (Time const &time, void (*f) (T1,T2,T3), T1 a1, T2 a2, T3 a3);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke
@@ -263,7 +263,7 @@
   template <typename T1, typename T2, typename T3, typename T4>
   static EventId Schedule (Time const &time, void (*f) (T1,T2,T3,T4), T1 a1, T2 a2, T3 a3, T4 a4);
   /**
-   * @param time the expiration time of the event.
+   * @param time the relative expiration time of the event.
    * @param f the function to invoke
    * @param a1 the first argument to pass to the function to invoke
    * @param a2 the second argument to pass to the function to invoke