merge with win32 tree
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu, 09 Aug 2007 13:42:42 +0200
changeset 1259 67584d6fc928
parent 1226 96d7a97b42a1 (current diff)
parent 1258 33d510db1e37 (diff)
child 1260 b24477e66df7
child 1272 67a2ba1143e0
child 1325 f3be9eed2d90
merge with win32 tree
samples/main-header.cc
src/common/chunk.cc
src/common/chunk.h
src/common/header.cc
src/common/packet-printer.cc
src/common/trailer.cc
--- a/doc/doxygen.conf	Thu Aug 09 13:38:04 2007 +0200
+++ b/doc/doxygen.conf	Thu Aug 09 13:42:42 2007 +0200
@@ -999,7 +999,7 @@
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = RUN_SELF_TESTS NS3_DEBUG_ENABLE
+PREDEFINED             = RUN_SELF_TESTS NS3_DEBUG_ENABLE NS3_ASSERT_ENABLE
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
--- a/samples/main-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-#include "ns3/packet.h"
-#include "ns3/header.h"
-#include <iostream>
-
-using namespace ns3;
-
-/* A sample Header implementation
- */
-class MyHeader : public Header 
-{
-public:
-  static uint32_t GetUid (void);
-
-  MyHeader ();
-  virtual ~MyHeader ();
-
-  void SetData (uint16_t data);
-  uint16_t GetData (void) const;
-private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
-  virtual uint32_t GetSerializedSize (void) const;
-
-  uint16_t m_data;
-};
-
-MyHeader::MyHeader ()
-{
-  // we must provide a public default constructor, 
-  // implicit or explicit, but never private.
-}
-MyHeader::~MyHeader ()
-{}
-
-uint32_t
-MyHeader::GetUid (void)
-{
-  // This string is used by the internals of the packet
-  // code to keep track of the packet metadata.
-  // You need to make sure that this string is absolutely
-  // unique. The code will detect any duplicate string.
-  static uint32_t uid = Header::Register<MyHeader> ("MyHeader.test.nsnam.org");
-  return uid;
-}
-
-std::string 
-MyHeader::DoGetName (void) const
-{
-  // This string is used to identify the type of 
-  // my header by the packet printing routines.
-  return "MYHEADER";
-}
-void 
-MyHeader::PrintTo (std::ostream &os) const
-{
-  // This method is invoked by the packet printing
-  // routines to print the content of my header.
-  os << "data=" << m_data << std::endl;
-}
-uint32_t
-MyHeader::GetSerializedSize (void) const
-{
-  // we reserve 2 bytes for our header.
-  return 2;
-}
-void
-MyHeader::SerializeTo (Buffer::Iterator start) const
-{
-  // we can serialize two bytes at the start of the buffer.
-  // we write them in network byte order.
-  start.WriteHtonU16 (m_data);
-}
-uint32_t
-MyHeader::DeserializeFrom (Buffer::Iterator start)
-{
-  // we can deserialize two bytes from the start of the buffer.
-  // we read them in network byte order and store them
-  // in host byte order.
-  m_data = start.ReadNtohU16 ();
-
-  // we return the number of bytes effectively read.
-  return 2;
-}
-
-void 
-MyHeader::SetData (uint16_t data)
-{
-  m_data = data;
-}
-uint16_t 
-MyHeader::GetData (void) const
-{
-  return m_data;
-}
-
-
-
-int main (int argc, char *argv[])
-{
-  // instantiate a header.
-  MyHeader sourceHeader;
-  sourceHeader.SetData (2);
-
-  // instantiate a packet
-  Packet p;
-  // and store my header into the packet.
-  p.AddHeader (sourceHeader);
-
-  // print the content of my packet on the standard output.
-  p.Print (std::cout);
-
-  // you can now remove the header from the packet:
-  MyHeader destinationHeader;
-  p.RemoveHeader (destinationHeader);
-
-  // and check that the destination and source
-  // headers contain the same values.
-  NS_ASSERT (sourceHeader.GetData () == destinationHeader.GetData ());
-
-  return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-packet-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,124 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#include "ns3/packet.h"
+#include "ns3/header.h"
+#include <iostream>
+
+using namespace ns3;
+
+/* A sample Header implementation
+ */
+class MyHeader : public Header 
+{
+public:
+  static uint32_t GetUid (void);
+
+  MyHeader ();
+  virtual ~MyHeader ();
+
+  void SetData (uint16_t data);
+  uint16_t GetData (void) const;
+
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  uint32_t GetSerializedSize (void) const;
+private:
+  uint16_t m_data;
+};
+
+MyHeader::MyHeader ()
+{
+  // we must provide a public default constructor, 
+  // implicit or explicit, but never private.
+}
+MyHeader::~MyHeader ()
+{}
+
+uint32_t
+MyHeader::GetUid (void)
+{
+  // This string is used by the internals of the packet
+  // code to keep track of the packet metadata.
+  // You need to make sure that this string is absolutely
+  // unique. The code will detect any duplicate string.
+  static uint32_t uid = AllocateUid<MyHeader> ("MyHeader.test.nsnam.org");
+  return uid;
+}
+
+std::string 
+MyHeader::GetName (void) const
+{
+  // This string is used to identify the type of 
+  // my header by the packet printing routines.
+  return "MYHEADER";
+}
+void 
+MyHeader::Print (std::ostream &os) const
+{
+  // This method is invoked by the packet printing
+  // routines to print the content of my header.
+  os << "data=" << m_data << std::endl;
+}
+uint32_t
+MyHeader::GetSerializedSize (void) const
+{
+  // we reserve 2 bytes for our header.
+  return 2;
+}
+void
+MyHeader::Serialize (Buffer::Iterator start) const
+{
+  // we can serialize two bytes at the start of the buffer.
+  // we write them in network byte order.
+  start.WriteHtonU16 (m_data);
+}
+uint32_t
+MyHeader::Deserialize (Buffer::Iterator start)
+{
+  // we can deserialize two bytes from the start of the buffer.
+  // we read them in network byte order and store them
+  // in host byte order.
+  m_data = start.ReadNtohU16 ();
+
+  // we return the number of bytes effectively read.
+  return 2;
+}
+
+void 
+MyHeader::SetData (uint16_t data)
+{
+  m_data = data;
+}
+uint16_t 
+MyHeader::GetData (void) const
+{
+  return m_data;
+}
+
+
+
+int main (int argc, char *argv[])
+{
+  // instantiate a header.
+  MyHeader sourceHeader;
+  sourceHeader.SetData (2);
+
+  // instantiate a packet
+  Packet p;
+  // and store my header into the packet.
+  p.AddHeader (sourceHeader);
+
+  // print the content of my packet on the standard output.
+  p.Print (std::cout);
+
+  // you can now remove the header from the packet:
+  MyHeader destinationHeader;
+  p.RemoveHeader (destinationHeader);
+
+  // and check that the destination and source
+  // headers contain the same values.
+  NS_ASSERT (sourceHeader.GetData () == destinationHeader.GetData ());
+
+  return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-packet-tag.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA
+ *
+ * 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 "ns3/tag.h"
+#include "ns3/packet.h"
+#include <iostream>
+
+using namespace ns3;
+
+// define this class in a public header
+class MyTag : public Tag
+{
+public:
+  // we have to define a public constructor
+  MyTag ();
+  // we have to define a public copy constructor
+  MyTag (const MyTag &other);
+  // we have to define a public destructor
+  ~MyTag ();
+  // we have to define a public static GetUid method
+  static uint32_t GetUid (void);
+  // we have to define a public Print method
+  void Print (std::ostream &os) const;
+  // we have to define a public GetSerializedSize method
+  uint32_t GetSerializedSize (void) const;
+  // we have to define a public Serialize method
+  void Serialize (Buffer::Iterator i) const;
+  // we have to define a public Deserialize method
+  uint32_t Deserialize (Buffer::Iterator i);
+  
+  // these are our accessors to our tag structure
+  void SetSimpleValue (uint8_t value);
+  uint8_t GetSimpleValue (void) const;
+private:
+  uint8_t m_simpleValue;
+};
+
+MyTag::MyTag ()
+{}
+MyTag::MyTag (const MyTag &other)
+  : m_simpleValue (other.m_simpleValue)
+{}
+MyTag::~MyTag ()
+{}
+uint32_t 
+MyTag::GetUid (void)
+{
+  // we input a unique string to AllocateUid
+  // to avoid name collisions.
+  static uint32_t uid = AllocateUid<MyTag> ("MyTag.tests.nsnam.org");
+  return uid;
+}
+void 
+MyTag::Print (std::ostream &os) const
+{
+  // print the content of this tag for Packet::PrintTags
+  os << "MyTag=0x" << std::hex << (uint32_t)m_simpleValue << std::dec;
+}
+uint32_t 
+MyTag::GetSerializedSize (void) const
+{
+  // we do not want to deal with parallel simulations
+  // so we return 0.
+  return 0;
+}
+void 
+MyTag::Serialize (Buffer::Iterator i) const
+{
+  // we will never be invoked because we are not doing
+  // parallel simulations so, we assert.
+  NS_ASSERT (false);
+}
+uint32_t
+MyTag::Deserialize (Buffer::Iterator i)
+{
+  // we will never be invoked because we are not doing
+  // parallel simulations so, we assert.
+  NS_ASSERT (false);
+  // theoretically, return the number of bytes read
+  return 0;
+}
+
+
+void 
+MyTag::SetSimpleValue (uint8_t value)
+{
+  m_simpleValue = value;
+}
+uint8_t 
+MyTag::GetSimpleValue (void) const
+{
+  return m_simpleValue;
+}
+
+
+int main (int argc, char *argv[])
+{
+  // create a tag.
+  MyTag tag;
+  tag.SetSimpleValue (0x56);
+
+  // store the tag in a packet.
+  Packet p;
+  p.AddTag (tag);
+
+  // create a copy of the packet
+  Packet aCopy = p;
+
+  // read the tag from the packet copy
+  MyTag tagCopy;
+  p.PeekTag (tagCopy);
+
+  // the copy and the original are the same !
+  NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
+
+  aCopy.PrintTags (std::cout);
+  std::cout << std::endl;
+
+  return 0;
+}
--- a/samples/wscript	Thu Aug 09 13:38:04 2007 +0200
+++ b/samples/wscript	Thu Aug 09 13:42:42 2007 +0200
@@ -13,8 +13,14 @@
     obj = bld.create_ns3_program('main-simulator')
     obj.source = 'main-simulator.cc'
 
-    obj = bld.create_ns3_program('main-header', ['common', 'simulator'])
-    obj.source = 'main-header.cc'
+    obj = bld.create_ns3_program('main-packet-header', ['common', 'simulator'])
+    obj.source = 'main-packet-header.cc'
+
+    obj = bld.create_ns3_program('main-packet-tag', ['common', 'simulator'])
+    obj.source = 'main-packet-tag.cc'
+
+    obj = bld.create_ns3_program('main-packet-printer', ['common', 'simulator', 'internet-node'])
+    obj.source = 'main-packet-printer.cc'
 
     obj = bld.create_ns3_program('main-test')
     obj.source = 'main-test.cc'
--- a/src/common/array-trace-resolver.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/array-trace-resolver.h	Thu Aug 09 13:42:42 2007 +0200
@@ -32,39 +32,11 @@
  * \brief a helper class to offer trace resolution for an array of objects.
  * \ingroup lowleveltracing
  */
-template <typename T>
+template <typename T, typename INDEX>
 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
@@ -91,31 +63,17 @@
 
 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)
+template <typename T, typename INDEX>
+ArrayTraceResolver<T,INDEX>::ArrayTraceResolver (TraceContext const &context,
+                                                 Callback<uint32_t> getSize, 
+                                                 Callback<T, uint32_t> get)
   : TraceResolver (context),
     m_getSize (getSize),
     m_get (get)
 {}
-template <typename T>
+template <typename T, typename INDEX>
 TraceResolver::TraceResolverList 
-ArrayTraceResolver<T>::DoLookup (std::string id) const
+ArrayTraceResolver<T,INDEX>::DoLookup (std::string id) const
 {
   TraceResolverList list;
   if (id == "*")
@@ -123,7 +81,7 @@
     for (uint32_t i = 0; i < m_getSize (); i++)
     {
       TraceContext context = GetContext ();
-      typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
+      INDEX index = i;
       context.Add (index);
       list.push_back (m_get (i)->CreateTraceResolver (context));
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-registry.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,117 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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 "chunk-registry.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+ChunkRegistry::InfoVector *
+ChunkRegistry::GetInfoVector (void)
+{
+  static InfoVector vec;
+  return &vec;
+}
+
+std::string 
+ChunkRegistry::GetUidStringFromUid (uint32_t uid)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.uidString;
+}
+uint32_t 
+ChunkRegistry::GetUidFromUidString (std::string uidString)
+{
+  uint32_t uid = 1;
+  InfoVector *vec = GetInfoVector ();
+  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+    {
+      if (i->uidString == uidString)
+	{
+	  return uid;
+	}
+      uid++;
+    }
+  NS_FATAL_ERROR ("Trying to access a non-registered Header or Trailer: \"" << uidString << "\". "<<
+		  "You could try calling NS_HEADER_ENSURE_REGISTER somewhere.");
+  return 0;
+}
+
+uint8_t *
+ChunkRegistry::GetStaticInstance (uint32_t uid)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.getStaticInstance ();
+}
+bool 
+ChunkRegistry::IsHeader (uint32_t uid)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.isHeader;
+}
+bool 
+ChunkRegistry::IsTrailer (uint32_t uid)
+{
+  return !IsHeader (uid);
+}
+uint32_t 
+ChunkRegistry::Deserialize (uint32_t uid, uint8_t *instance, Buffer::Iterator i)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.deserialize (instance, i);
+}
+void 
+ChunkRegistry::Print (uint32_t uid, uint8_t *instance, std::ostream &os)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.print (instance, os);
+}
+std::string
+ChunkRegistry::GetName (uint32_t uid, uint8_t *instance)
+{ 
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  return info.getName (instance);
+}
+void 
+ChunkRegistry::InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
+				    uint32_t packetUid, uint32_t size, 
+				    Ptr<CallbackImplBase> callback)
+{
+  InfoVector *vec = GetInfoVector ();
+  NS_ASSERT (uid >= 1 && uid <= vec->size ());
+  Info info = (*vec)[uid - 1];
+  info.invokePrintCallback (instance, os, packetUid, size, callback);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-registry.h	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,180 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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 CHUNK_REGISTRY_H
+#define CHUNK_REGISTRY_H
+
+#include <stdint.h>
+#include <ostream>
+#include "buffer.h"
+#include "ns3/ptr.h"
+#include "ns3/callback.h"
+
+namespace ns3 {
+
+/**
+ * \brief this registry keeps track of all different
+ * types of headers and trailers and assigns to each of them
+ * a unique integer.
+ * \internal
+ */
+class ChunkRegistry
+{
+public:
+  template <typename T>
+  static uint32_t RegisterHeader (std::string uuid);
+  template <typename T>
+  static uint32_t RegisterTrailer (std::string uuid);
+
+  static std::string GetUidStringFromUid (uint32_t uid);
+  static uint32_t GetUidFromUidString (std::string uidString);
+  static uint8_t *GetStaticInstance (uint32_t uid);
+  static uint32_t Deserialize (uint32_t uid, uint8_t *instance, Buffer::Iterator i);
+  static void Print (uint32_t uid, uint8_t *instance, std::ostream &os);
+  static std::string GetName (uint32_t uid, uint8_t *instance);
+  static bool IsHeader (uint32_t uid);
+  static bool IsTrailer (uint32_t uid);
+  static void InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
+				   uint32_t packetUid, uint32_t size, 
+				   Ptr<CallbackImplBase> callback);
+private:
+  typedef uint8_t *(*GetStaticInstanceCb) (void);
+  typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
+  typedef void (*PrintCb) (uint8_t *,std::ostream &);
+  typedef std::string (*GetNameCb) (uint8_t *);
+  typedef void (*InvokePrintCallbackCb) (uint8_t *instance, std::ostream &os,
+					 uint32_t packetUid, uint32_t size, 
+					 Ptr<CallbackImplBase> callback);
+  struct Info {
+    std::string uidString;
+    bool isHeader;
+    GetStaticInstanceCb getStaticInstance;
+    DeserializeCb deserialize;
+    PrintCb print;
+    GetNameCb getName;
+    InvokePrintCallbackCb invokePrintCallback;
+  };
+  typedef std::vector<struct Info> InfoVector;
+  static InfoVector *GetInfoVector (void);
+  template <typename T>
+  static uint8_t *DoGetStaticInstance (void);
+  template <typename T>
+  static uint32_t DoDeserialize (uint8_t *instance, Buffer::Iterator i);
+  template <typename T>
+  static void DoPrint (uint8_t *instance, std::ostream &os);
+  template <typename T>
+  static std::string DoGetName (uint8_t *instance);
+  template <typename T>
+  static void DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
+				     uint32_t packetUid, uint32_t size, 
+				     Ptr<CallbackImplBase> callback);
+  template <typename T>
+  static uint32_t GetUid (bool isHeader, std::string uidString);
+
+};
+
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+uint32_t 
+ChunkRegistry::RegisterHeader (std::string uuid)
+{
+  return GetUid<T> (true, uuid);
+}
+template <typename T>
+uint32_t 
+ChunkRegistry::RegisterTrailer (std::string uuid)
+{
+  return GetUid<T> (false, uuid);
+}
+
+template <typename T>
+uint32_t 
+ChunkRegistry::GetUid (bool isHeader, std::string uidString)
+{
+  InfoVector *vec = GetInfoVector ();
+  uint32_t uid = 1; 
+  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+    {
+      if (i->uidString == uidString)
+	{
+	  return uid;
+	}
+      uid++;
+    }
+  Info info;
+  info.getStaticInstance = &ChunkRegistry::DoGetStaticInstance<T>;
+  info.print = &ChunkRegistry::DoPrint<T>;
+  info.getName = &ChunkRegistry::DoGetName<T>;
+  info.deserialize = &ChunkRegistry::DoDeserialize<T>;
+  info.invokePrintCallback = &ChunkRegistry::DoInvokePrintCallback<T>;
+  info.uidString = uidString;
+  info.isHeader = isHeader;
+  vec->push_back (info);
+  return vec->size ();
+}
+
+template <typename T>
+uint8_t *
+ChunkRegistry::DoGetStaticInstance ()
+{
+  static T instance;
+  return reinterpret_cast<uint8_t *> (&instance);
+}
+template <typename T>
+uint32_t 
+ChunkRegistry::DoDeserialize (uint8_t *instance, Buffer::Iterator i)
+{
+  T *obj = reinterpret_cast<T *> (instance);
+  return obj->Deserialize (i);
+}
+template <typename T>
+void 
+ChunkRegistry::DoPrint (uint8_t *instance, std::ostream &os)
+{
+  T *obj = reinterpret_cast<T *> (instance);
+  obj->Print (os);
+}
+template <typename T>
+std::string
+ChunkRegistry::DoGetName (uint8_t *instance)
+{
+  T *obj = reinterpret_cast<T *> (instance);
+  return obj->GetName ();
+}
+template <typename T>
+void 
+ChunkRegistry::DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
+				      uint32_t packetUid, uint32_t size, 
+				      Ptr<CallbackImplBase> callback)
+{
+  T *obj = reinterpret_cast<T *> (instance);
+  Callback<void,std::ostream&,uint32_t,uint32_t,const T*> cb;
+  cb.Assign (callback);
+  cb (os, packetUid, size, obj);
+}
+
+} // namespace ns3
+
+#endif /* CHUNK_H */
--- a/src/common/chunk.cc	Thu Aug 09 13:38:04 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,161 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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 "chunk.h"
-#include "ns3/assert.h"
-
-namespace ns3 {
-
-Chunk::Chunk ()
-{}
-
-Chunk::~Chunk ()
-{}
-
-std::string
-Chunk::GetName (void) const
-{
-  return DoGetName ();
-}
-void 
-Chunk::Print (std::ostream &os) const
-{
-  PrintTo (os);
-}
-uint32_t
-Chunk::GetSize (void) const
-{
-  return GetSerializedSize ();
-}
-void
-Chunk::Serialize (Buffer::Iterator start) const
-{
-  SerializeTo (start);
-}
-uint32_t
-Chunk::Deserialize (Buffer::Iterator start)
-{
-  uint32_t deserialized = DeserializeFrom (start);
-  return deserialized;
-}
-std::ostream& operator<< (std::ostream& os, Chunk const& chunk)
-{
-  chunk.Print (os);
-  return os;
-}
-
-
-/**************************************
- * The Chunk Registry below
- ***************************************/
-
-
-ChunkRegistry::InfoVector *
-ChunkRegistry::GetInfoVector (void)
-{
-  static InfoVector vec;
-  return &vec;
-}
-
-std::string 
-ChunkRegistry::GetUidStringFromUid (uint32_t uid)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.uidString;
-}
-uint32_t 
-ChunkRegistry::GetUidFromUidString (std::string uidString)
-{
-  uint32_t uid = 1;
-  InfoVector *vec = GetInfoVector ();
-  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
-    {
-      if (i->uidString == uidString)
-	{
-	  return uid;
-	}
-      uid++;
-    }
-  NS_FATAL_ERROR ("Trying to access a non-registered Header or Trailer: \"" << uidString << "\". "<<
-		  "You could try calling NS_HEADER_ENSURE_REGISTER somewhere.");
-  return 0;
-}
-
-uint8_t *
-ChunkRegistry::GetStaticInstance (uint32_t uid)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.getStaticInstance ();
-}
-bool 
-ChunkRegistry::IsHeader (uint32_t uid)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.isHeader;
-}
-bool 
-ChunkRegistry::IsTrailer (uint32_t uid)
-{
-  return !IsHeader (uid);
-}
-uint32_t 
-ChunkRegistry::Deserialize (uint32_t uid, uint8_t *instance, Buffer::Iterator i)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.deserialize (instance, i);
-}
-void 
-ChunkRegistry::Print (uint32_t uid, uint8_t *instance, std::ostream &os)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.print (instance, os);
-}
-std::string
-ChunkRegistry::GetName (uint32_t uid, uint8_t *instance)
-{ 
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  return info.getName (instance);
-}
-void 
-ChunkRegistry::InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
-				    uint32_t packetUid, uint32_t size, 
-				    Ptr<CallbackImplBase> callback)
-{
-  InfoVector *vec = GetInfoVector ();
-  NS_ASSERT (uid >= 1 && uid <= vec->size ());
-  Info info = (*vec)[uid - 1];
-  info.invokePrintCallback (instance, os, packetUid, size, callback);
-}
-
-
-} // namespace ns3
--- a/src/common/chunk.h	Thu Aug 09 13:38:04 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,200 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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 CHUNK_H
-#define CHUNK_H
-
-#include <stdint.h>
-#include <ostream>
-#include "buffer.h"
-#include "ns3/ptr.h"
-#include "ns3/callback.h"
-
-namespace ns3 {
-
-class Chunk {
-public:
-  Chunk ();
-  virtual ~Chunk ();
-
-  std::string GetName (void) const;
-  void Print (std::ostream &os) const;
-  uint32_t GetSize (void) const;
-  void Serialize (Buffer::Iterator start) const;
-  uint32_t Deserialize (Buffer::Iterator start);
-private:
-  virtual std::string DoGetName (void) const = 0;
-  virtual void PrintTo (std::ostream &os) const = 0;
-  virtual uint32_t GetSerializedSize (void) const = 0;
-  virtual void SerializeTo (Buffer::Iterator i) const = 0;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator i) = 0;
-};
-
-std::ostream& operator<< (std::ostream& os, Chunk const& chunk);
-
-/**
- * \brief this registry keeps track of all different
- * types of headers and trailers and assigns to each of them
- * a unique integer.
- * \internal
- */
-class ChunkRegistry
-{
-public:
-  template <typename T>
-  static uint32_t RegisterHeader (std::string uuid);
-  template <typename T>
-  static uint32_t RegisterTrailer (std::string uuid);
-
-  static std::string GetUidStringFromUid (uint32_t uid);
-  static uint32_t GetUidFromUidString (std::string uidString);
-  static uint8_t *GetStaticInstance (uint32_t uid);
-  static uint32_t Deserialize (uint32_t uid, uint8_t *instance, Buffer::Iterator i);
-  static void Print (uint32_t uid, uint8_t *instance, std::ostream &os);
-  static std::string GetName (uint32_t uid, uint8_t *instance);
-  static bool IsHeader (uint32_t uid);
-  static bool IsTrailer (uint32_t uid);
-  static void InvokePrintCallback (uint32_t uid, uint8_t *instance, std::ostream &os,
-				   uint32_t packetUid, uint32_t size, 
-				   Ptr<CallbackImplBase> callback);
-private:
-  typedef uint8_t *(*GetStaticInstanceCb) (void);
-  typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
-  typedef void (*PrintCb) (uint8_t *,std::ostream &);
-  typedef std::string (*GetNameCb) (uint8_t *);
-  typedef void (*InvokePrintCallbackCb) (uint8_t *instance, std::ostream &os,
-					 uint32_t packetUid, uint32_t size, 
-					 Ptr<CallbackImplBase> callback);
-  struct Info {
-    std::string uidString;
-    bool isHeader;
-    GetStaticInstanceCb getStaticInstance;
-    DeserializeCb deserialize;
-    PrintCb print;
-    GetNameCb getName;
-    InvokePrintCallbackCb invokePrintCallback;
-  };
-  typedef std::vector<struct Info> InfoVector;
-  static InfoVector *GetInfoVector (void);
-  template <typename T>
-  static uint8_t *DoGetStaticInstance (void);
-  template <typename T>
-  static uint32_t DoDeserialize (uint8_t *instance, Buffer::Iterator i);
-  template <typename T>
-  static void DoPrint (uint8_t *instance, std::ostream &os);
-  template <typename T>
-  static std::string DoGetName (uint8_t *instance);
-  template <typename T>
-  static void DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
-				     uint32_t packetUid, uint32_t size, 
-				     Ptr<CallbackImplBase> callback);
-  template <typename T>
-  static uint32_t GetUid (bool isHeader, std::string uidString);
-
-};
-
-
-} // namespace ns3
-
-namespace ns3 {
-
-template <typename T>
-uint32_t 
-ChunkRegistry::RegisterHeader (std::string uuid)
-{
-  return GetUid<T> (true, uuid);
-}
-template <typename T>
-uint32_t 
-ChunkRegistry::RegisterTrailer (std::string uuid)
-{
-  return GetUid<T> (false, uuid);
-}
-
-template <typename T>
-uint32_t 
-ChunkRegistry::GetUid (bool isHeader, std::string uidString)
-{
-  InfoVector *vec = GetInfoVector ();
-  uint32_t uid = 1; 
-  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
-    {
-      if (i->uidString == uidString)
-	{
-	  return uid;
-	}
-      uid++;
-    }
-  Info info;
-  info.getStaticInstance = &ChunkRegistry::DoGetStaticInstance<T>;
-  info.print = &ChunkRegistry::DoPrint<T>;
-  info.getName = &ChunkRegistry::DoGetName<T>;
-  info.deserialize = &ChunkRegistry::DoDeserialize<T>;
-  info.invokePrintCallback = &ChunkRegistry::DoInvokePrintCallback<T>;
-  info.uidString = uidString;
-  info.isHeader = isHeader;
-  vec->push_back (info);
-  return vec->size ();
-}
-
-template <typename T>
-uint8_t *
-ChunkRegistry::DoGetStaticInstance ()
-{
-  static T instance;
-  return reinterpret_cast<uint8_t *> (&instance);
-}
-template <typename T>
-uint32_t 
-ChunkRegistry::DoDeserialize (uint8_t *instance, Buffer::Iterator i)
-{
-  T *obj = reinterpret_cast<T *> (instance);
-  return obj->Deserialize (i);
-}
-template <typename T>
-void 
-ChunkRegistry::DoPrint (uint8_t *instance, std::ostream &os)
-{
-  T *obj = reinterpret_cast<T *> (instance);
-  obj->Print (os);
-}
-template <typename T>
-std::string
-ChunkRegistry::DoGetName (uint8_t *instance)
-{
-  T *obj = reinterpret_cast<T *> (instance);
-  return obj->GetName ();
-}
-template <typename T>
-void 
-ChunkRegistry::DoInvokePrintCallback (uint8_t *instance, std::ostream &os,
-				      uint32_t packetUid, uint32_t size, 
-				      Ptr<CallbackImplBase> callback)
-{
-  T *obj = reinterpret_cast<T *> (instance);
-  Callback<void,std::ostream&,uint32_t,uint32_t,const T*> cb;
-  cb.Assign (callback);
-  cb (os, packetUid, size, obj);
-}
-
-} // namespace ns3
-
-#endif /* CHUNK_H */
--- a/src/common/composite-trace-resolver.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/composite-trace-resolver.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -30,6 +30,14 @@
 {}
 
 void 
+CompositeTraceResolver::Add (std::string name, 
+                             Callback<TraceResolver *,TraceContext const &> createResolver)
+{
+  TraceContext traceContext = GetContext ();
+  DoAdd (name, createResolver, traceContext);
+}
+
+void 
 CompositeTraceResolver::DoAdd (std::string name, 
 			       Callback<TraceResolver *,TraceContext const &> createResolver,
 			       TraceContext const &context)
@@ -107,20 +115,53 @@
 #ifdef RUN_SELF_TESTS
 
 #include "ns3/test.h"
+#include "trace-context-element.h"
 
 namespace ns3 {
 
+class TraceSourceTest : public TraceContextElement
+{
+public:
+  enum Sources {
+    DOUBLEA,
+    DOUBLEB,
+    SUBRESOLVER,
+  };
+  static uint16_t GetUid (void) 
+  {static uint16_t uid = AllocateUid<TraceSourceTest> ("TraceSourceTest"); return uid;}
+  void Print (std::ostream &os)
+  {os << "tracesource=";
+    if (m_sources == DOUBLEA) {os << "doubleA";}
+    else if (m_sources == DOUBLEB) {os << "doubleB";}
+    else if (m_sources == SUBRESOLVER) {os << "subresolver";}
+  }
+  TraceSourceTest () : m_sources (TraceSourceTest::DOUBLEA) {}
+  TraceSourceTest (enum Sources sources) :m_sources (sources) {}
+  bool IsDoubleA (void) {return m_sources == TraceSourceTest::DOUBLEA;}
+  bool IsDoubleB (void) {return m_sources == TraceSourceTest::DOUBLEB;}
+private:
+  enum TraceSourceTest::Sources m_sources;
+};
+
+class SubTraceSourceTest : public TraceContextElement
+{
+public:
+  enum Sources {
+    INT,
+  };
+  static uint16_t GetUid (void) 
+  {static uint16_t uid = AllocateUid<SubTraceSourceTest> ("SubTraceSourceTest"); return uid;}
+  void Print (std::ostream &os)
+  {os << "subtracesource=int";}
+  SubTraceSourceTest () : m_sources (SubTraceSourceTest::INT) {}
+  SubTraceSourceTest (enum Sources sources) : m_sources (sources) {}
+private:
+  enum Sources m_sources;
+};
+
 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);
@@ -144,19 +185,19 @@
 void 
 CompositeTraceResolverTest::TraceDouble (TraceContext const &context, double v)
 {
-  enum CompositeTraceResolverTest::TraceSources source;
+  TraceSourceTest source;
   context.Get (source);
-  switch (source)
+  if (source.IsDoubleA ())
     {
-    case TEST_TRACE_DOUBLEA:
       m_gotDoubleA = true;
-      break;
-    case TEST_TRACE_DOUBLEB:
+    }
+  else if (source.IsDoubleB ())
+    {
       m_gotDoubleB = true;
-      break;
-    default:
+    }
+  else
+    {
       NS_FATAL_ERROR ("should not get any other trace source in this sink");
-      break;
     }
   
 }
@@ -171,7 +212,8 @@
 CompositeTraceResolverTest::CreateSubResolver (TraceContext const &context)
 {
   CompositeTraceResolver *subresolver = new CompositeTraceResolver (context);
-  subresolver->Add ("trace-int", m_traceInt, TEST_SUBTRACE_INT);
+  subresolver->Add ("trace-int", m_traceInt, 
+                    SubTraceSourceTest (SubTraceSourceTest::INT));
   return subresolver;
 }
 bool 
@@ -185,8 +227,10 @@
 
   CompositeTraceResolver resolver (context) ;
 
-  resolver.Add ("trace-double-a", traceDoubleA, TEST_TRACE_DOUBLEA);
-  resolver.Add ("trace-double-b", traceDoubleB, TEST_TRACE_DOUBLEB);
+  resolver.Add ("trace-double-a", traceDoubleA, 
+                TraceSourceTest (TraceSourceTest::DOUBLEA));
+  resolver.Add ("trace-double-b", traceDoubleB, 
+                TraceSourceTest (TraceSourceTest::DOUBLEB));
 
   resolver.Connect ("/*", MakeCallback (&CompositeTraceResolverTest::TraceDouble, this));
 
@@ -279,7 +323,7 @@
 
   resolver.Add ("subresolver", 
 		MakeCallback (&CompositeTraceResolverTest::CreateSubResolver, this),
-		TEST_TRACE_SUBRESOLVER);
+		TraceSourceTest (TraceSourceTest::SUBRESOLVER));
 
   resolver.Connect ("/subresolver/trace-int", 
 		    MakeCallback (&CompositeTraceResolverTest::TraceInt, this));
--- a/src/common/composite-trace-resolver.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/composite-trace-resolver.h	Thu Aug 09 13:42:42 2007 +0200
@@ -111,6 +111,18 @@
   void Add (std::string name, 
             Callback<TraceResolver *,TraceContext const &> createResolver,
             T const &context);
+
+  /**
+   * \param name name of child trace resolver
+   * \param createResolver a trace resolver constructor
+   *
+   * 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.
+   */
+  void Add (std::string name, 
+            Callback<TraceResolver *,TraceContext const &> createResolver);
 private:
   template <typename SOURCE, typename CONTEXT>
   void DoAddTraceSource (std::string name,
@@ -205,7 +217,6 @@
   DoAdd (name, createResolver, traceContext);
 }
 
-
 }//namespace ns3
 
 #endif /* COMPOSITE_TRACE_RESOLVER_H */
--- a/src/common/header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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 "header.h"
-
-namespace ns3 {
-
-Header::~Header ()
-{}
-
-} // namespace ns3
--- a/src/common/header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -22,10 +22,10 @@
 #ifndef HEADER_H
 #define HEADER_H
 
-#include "chunk.h"
+#include "chunk-registry.h"
 
 /**
- * \relates Header
+ * \relates ns3::Header
  * \brief this macro should be instantiated exactly once for each
  *        new type of Header
  *
@@ -37,15 +37,14 @@
  * Note: This macro is _absolutely_ needed if you try to run a
  * distributed simulation.
  */
-#define NS_HEADER_ENSURE_REGISTERED(x)          \
-namespace {                                     \
-static class thisisaveryverylongclassname       \
-{                                               \
-public:                                         \
-  thisisaveryverylongclassname ()               \
-  { uint32_t uid; uid = x::GetUid ();}          \
-} g_thisisanotherveryveryverylongname;          \
-}
+#define NS_HEADER_ENSURE_REGISTERED(x)         \
+static class thisisaveryverylongclassname ##x  \
+{                                              \
+ public:                                       \
+  thisisaveryverylongclassname ##x ()          \
+    { uint32_t uid; uid = x::GetUid ();}       \
+} g_thisisanotherveryveryverylongname ## x;
+
 
 namespace ns3 {
 
@@ -53,96 +52,51 @@
  * \brief Protocol header serialization and deserialization.
  *
  * Every Protocol header which needs to be inserted or removed
- * from a Packet instance must derive from this abstract base class
- * and implement the private pure virtual methods listed below:
- *   - ns3::Header::SerializeTo
- *   - ns3::Header::DeserializeFrom
- *   - ns3::Header::GetSerializedSize
- *   - ns3::Header::PrintTo
- *   - ns3::Header::DoGetName
- *
- * Each header must also make sure that:
- *   - it defines a public default constructor
- *   - it defines a public static method named GetUid which returns a 32 bit integer
+ * from a Packet instance must derive from this base class and
+ * implement the following public methods:
+ *   - a default constructor: is used by the internal implementation
+ *     if the Packet class.
+ *   - a static method named GetUid: is used to uniquely identify
+ *     the type of each header. This method shall return a unique
+ *     integer allocated with Header::AllocateUid.
+ *   - a method named Serialize: is used by Packet::AddHeader to
+ *     store a header into the byte buffer of a packet.
+ *     The input iterator points to the start of the byte buffer in
+ *     which the header should write its data. The data written
+ *     is expected to match bit-for-bit the representation of this
+ *     header in a real network.
+ *   - a method named GetSerializedSize: is used by Packet::AddHeader
+ *     to store a header into the byte buffer of a packet. This method
+ *     should return the number of bytes which are needed to store
+ *     the full header data by Serialize.
+ *   - a method named Deserialize: is used by Packet::RemoveHeader to
+ *     re-create a header from the byte buffer of a packet. The input
+ *     iterator points to the start of the byte buffer from which
+ *     the header should read its data. The data read is expected to
+ *     match bit-for-bit the representation of this header in real
+ *     networks. This method shall return an integer which identifies
+ *     the number of bytes read.
+ *   - a method named Print: is used by Packet::Print to print the 
+ *     content of a header as ascii data to a c++ output stream.
+ *     Although the header is free to format its output as it
+ *     wishes, it is recommended to follow a few rules to integrate
+ *     with the packet pretty printer: start with flags, small field 
+ *     values located between a pair of parens. Values should be separated 
+ *     by whitespace. Follow the parens with the important fields, 
+ *     separated by whitespace.
+ *     i.e.: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
+ *   - a method named GetName: is used by Packet::Print to print
+ *     header fragments. This method should return a user-readable
+ *     single word as all capitalized letters.
  *
- * The latter should look like the following:
- * \code
- * // in the header,
- * class MyHeader : public Header
- * {
- * public:
- *   static uint32_t GetUid (void);
- * };
- *
- * // in the source file:
- * NS_HEADER_ENSURE_REGISTERED (MyHeader);
- *
- * uint32_t MyHeader::GetUid (void)
- * {
- *   static uint32_t uid = Header::Register<MyHeader> ("MyHeader.unique.prefix");
- *   return uid;
- * }
- * \endcode
- *
- * Sample code which shows how to create a new Header, and how to use it, 
- * is shown in the sample file samples/main-header.cc
+ * Sample code which shows how to create a new type of Header, and how to use it, 
+ * is shown in the sample file samples/main-packet-header.cc
  */
-class Header : public Chunk {
-public:
-  virtual ~Header ();
+class Header 
+{
 protected:
   template <typename T>
-  static uint32_t Register (std::string uuid);
-private:
-  /**
-   * \returns a user-readable name to identify this type of header.
-   *
-   * The string returned is expected to be a single word with 
-   * all capital letters
-   */
-  virtual std::string DoGetName (void) const = 0;
-  /**
-   * \param os the std output stream in which this 
-   *       protocol header must print itself.
-   *
-   * Although the header is free to format its output as it
-   * wishes, it is recommended to follow a few rules to integrate
-   * with the packet pretty printer:
-   *   - start with flags, small field values located between a
-   *     pair of parens. Values should be separated by whitespace.
-   *   - follow the parens with the important fields, separated by
-   *     whitespace.
-   * i.e.:
-   * (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
-   */
-  virtual void PrintTo (std::ostream &os) const = 0;
-
-  /**
-   * \returns the size of the serialized Header.
-   *
-   * This method is used by Packet::AddHeader to reserve
-   * enough room in the packet byte buffer prior to calling
-   * Header::Serialize.
-   */
-  virtual uint32_t GetSerializedSize (void) const = 0;
-
-  /**
-   * \param start the buffer iterator in which the protocol header
-   *    must serialize itself. This iterator identifies 
-   *    the start of the buffer.
-   */
-  virtual void SerializeTo (Buffer::Iterator start) const = 0;
-  /**
-   * \param start the buffer iterator from which the protocol header must
-   *    deserialize itself. This iterator identifies 
-   *    the start of the buffer.
-   * \returns the number of bytes read from the buffer
-   *
-   * The value returned is used to trim the packet byte buffer of the 
-   * corresponding amount when this method is invoked from 
-   * Packet::RemoveHeader
-   */
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start) = 0;
+  static uint32_t AllocateUid (std::string uuid);
 };
 
 } // namespace ns3
@@ -151,12 +105,11 @@
 
 template <typename T>
 uint32_t 
-Header::Register (std::string uuid)
+Header::AllocateUid (std::string uuid)
 {
   return ChunkRegistry::RegisterHeader<T> (uuid);
 }
 
-
 } // namespace ns3
 
 #endif /* HEADER_H */
--- a/src/common/packet-metadata-test.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet-metadata-test.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -38,12 +38,12 @@
   static uint32_t GetUid (void);
   HistoryHeader ();
   bool IsOk (void) const;
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
   bool m_ok;
 };
 
@@ -53,7 +53,7 @@
 {
   std::ostringstream oss;
   oss << N << "HistoryHeader.ns3";
-  static uint32_t uid = Header::Register<HistoryHeader<N> > (oss.str());
+  static uint32_t uid = AllocateUid<HistoryHeader<N> > (oss.str());
   return uid;
 }
 
@@ -71,7 +71,7 @@
 
 template <int N>
 std::string 
-HistoryHeader<N>::DoGetName (void) const
+HistoryHeader<N>::GetName (void) const
 {
   std::ostringstream oss;
   oss << N;
@@ -80,7 +80,7 @@
 
 template <int N>
 void 
-HistoryHeader<N>::PrintTo (std::ostream &os) const
+HistoryHeader<N>::Print (std::ostream &os) const
 {
   NS_ASSERT (false);
 }
@@ -92,13 +92,13 @@
 }
 template <int N>
 void 
-HistoryHeader<N>::SerializeTo (Buffer::Iterator start) const
+HistoryHeader<N>::Serialize (Buffer::Iterator start) const
 {
   start.WriteU8 (N, N);
 }
 template <int N>
 uint32_t
-HistoryHeader<N>::DeserializeFrom (Buffer::Iterator start)
+HistoryHeader<N>::Deserialize (Buffer::Iterator start)
 {
   m_ok = true;
   for (int i = 0; i < N; i++)
@@ -118,12 +118,12 @@
   static uint32_t GetUid (void);
   HistoryTrailer ();
   bool IsOk (void) const;
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
   bool m_ok;
 };
 
@@ -133,7 +133,7 @@
 {
   std::ostringstream oss;
   oss << N << "HistoryTrailer.ns3";
-  static uint32_t uid = Trailer::Register<HistoryTrailer<N> > (oss.str ());
+  static uint32_t uid = AllocateUid<HistoryTrailer<N> > (oss.str ());
   return uid;
 }
 
@@ -152,7 +152,7 @@
 
 template <int N>
 std::string 
-HistoryTrailer<N>::DoGetName (void) const
+HistoryTrailer<N>::GetName (void) const
 {
   std::ostringstream oss;
   oss << N;
@@ -160,7 +160,7 @@
 }
 template <int N>
 void 
-HistoryTrailer<N>::PrintTo (std::ostream &os) const
+HistoryTrailer<N>::Print (std::ostream &os) const
 {
   NS_ASSERT (false);
 }
@@ -172,14 +172,14 @@
 }
 template <int N>
 void 
-HistoryTrailer<N>::SerializeTo (Buffer::Iterator start) const
+HistoryTrailer<N>::Serialize (Buffer::Iterator start) const
 {
   start.Prev (N);
   start.WriteU8 (N, N);
 }
 template <int N>
 uint32_t
-HistoryTrailer<N>::DeserializeFrom (Buffer::Iterator start)
+HistoryTrailer<N>::Deserialize (Buffer::Iterator start)
 {
   m_ok = true;
   start.Prev (N);
--- a/src/common/packet-metadata.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet-metadata.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -23,8 +23,8 @@
 #include "ns3/fatal-error.h"
 #include "ns3/debug.h"
 #include "packet-metadata.h"
-#include "chunk.h"
 #include "buffer.h"
+#include "chunk-registry.h"
 
 NS_DEBUG_COMPONENT_DEFINE ("PacketMetadata");
 
--- a/src/common/packet-printer.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet-printer.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -20,6 +20,7 @@
  */
 
 #include "packet-printer.h"
+#include "chunk-registry.h"
 
 namespace ns3 {
 
--- a/src/common/packet-printer.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet-printer.h	Thu Aug 09 13:42:42 2007 +0200
@@ -24,7 +24,6 @@
 #include "ns3/callback.h"
 #include "ns3/ptr.h"
 #include "buffer.h"
-#include "chunk.h"
 #include <vector>
 
 namespace ns3 {
--- a/src/common/packet.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -126,6 +126,12 @@
 }
 
 void 
+Packet::PrintTags (std::ostream &os) const
+{
+  m_tags.Print (os);
+}
+
+void 
 Packet::Print (std::ostream &os) const
 {
   m_metadata.Print (os, m_buffer, PacketPrinter ());
--- a/src/common/packet.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/packet.h	Thu Aug 09 13:42:42 2007 +0200
@@ -27,6 +27,7 @@
 #include "trailer.h"
 #include "tags.h"
 #include "packet-metadata.h"
+#include "tag.h"
 #include "ns3/callback.h"
 #include "ns3/assert.h"
 
@@ -62,15 +63,11 @@
  *
  * Implementing a new type of Header or Trailer for a new protocol is 
  * pretty easy and is a matter of creating a subclass of the ns3::Header 
- * or of the ns3::Trailer base class, and implementing the 5 pure virtual 
- * methods defined in either of the two base classes. Users _must_
- * also make sure that they class defines a public default constructor and
- * a public method named GetUid, as documented in the ns3::Header and ns::Trailer
- * API documentations.
+ * or of the ns3::Trailer base class, and implementing the methods
+ * described in their respective API documentation.
  *
  * Implementing a new type of Tag requires roughly the same amount of
- * work: users must implement a total of 6 methods which are described in
- * \ref tags
+ * work and this work is described in the ns3::Tag API documentation.
  *
  * The performance aspects of the Packet API are discussed in 
  * \ref packetperf
@@ -118,7 +115,7 @@
   uint32_t GetSize (void) const;
   /**
    * Add header to this packet. This method invokes the
-   * ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo 
+   * GetSerializedSize and Serialize
    * methods to reserve space in the buffer and request the 
    * header to serialize itself in the packet buffer.
    *
@@ -128,7 +125,7 @@
   void AddHeader (T const &header);
   /**
    * Deserialize and remove the header from the internal buffer.
-   * This method invokes ns3::Chunk::DeserializeFrom.
+   * This method invokes Deserialize.
    *
    * \param header a reference to the header to remove from the internal buffer.
    * \returns the number of bytes removed from the packet.
@@ -137,7 +134,7 @@
   uint32_t RemoveHeader (T &header);
   /**
    * Add trailer to this packet. This method invokes the
-   * ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo 
+   * GetSerializedSize and Serialize
    * methods to reserve space in the buffer and request the trailer 
    * to serialize itself in the packet buffer.
    *
@@ -147,7 +144,7 @@
   void AddTrailer (T const &trailer);
   /**
    * Remove a deserialized trailer from the internal buffer.
-   * This method invokes the ns3::Chunk::DeserializeFrom method.
+   * This method invokes the Deserialize method.
    *
    * \param trailer a reference to the trailer to remove from the internal buffer.
    * \returns the number of bytes removed from the end of the packet.
@@ -157,7 +154,8 @@
   /**
    * Attach a tag to this packet. The tag is fully copied
    * in a packet-specific internal buffer. This operation 
-   * is expected to be really fast.
+   * is expected to be really fast. The copy constructor of the
+   * tag is invoked to copy it into the tag buffer.
    *
    * \param tag a pointer to the tag to attach to this packet.
    */
@@ -184,6 +182,8 @@
   /**
    * Copy a tag stored internally to the input tag. If no instance
    * of this tag is present internally, the input tag is not modified.
+   * The copy constructor of the tag is invoked to copy it into the 
+   * input tag variable.
    *
    * \param tag a pointer to the tag to read from this packet
    * \returns true if an instance of this tag type is stored
@@ -197,6 +197,14 @@
    */
   void RemoveAllTags (void);
   /**
+   * \param os output stream in which the data should be printed.
+   *
+   * Iterate over the tags present in this packet, and
+   * invoke the Print method of each tag stored in the packet.
+   */
+  void PrintTags (std::ostream &os) const;
+
+  /**
    * Concatenate the input packet at the end of the current
    * packet. This does not alter the uid of either packet.
    *
@@ -289,18 +297,24 @@
    * serialized representation contains a copy of the packet byte buffer,
    * the tag list, and the packet metadata (if there is one).
    *
+   * This method will trigger calls to the Serialize and GetSerializedSize
+   * methods of each tag stored in this packet.
+   *
    * This method will typically be used by parallel simulations where
    * the simulated system is partitioned and each partition runs on
    * a different CPU.
    */
   Buffer Serialize (void) const;
   /**
-   * \param a byte buffer
+   * \param buffer a byte buffer
    *
    * This method reads a byte buffer as created by Packet::Serialize
-   * and restores the state of the Packet to what it was prio to
+   * and restores the state of the Packet to what it was prior to
    * calling Serialize.
    *
+   * This method will trigger calls to the Deserialize method
+   * of each tag stored in this packet.
+   *
    * This method will typically be used by parallel simulations where
    * the simulated system is partitioned and each partition runs on
    * a different CPU.
@@ -315,59 +329,6 @@
 };
 
 /**
- * \defgroup tags Packet Tags
- *
- * A tag is a class which must define:
- *  - a public default constructor
- *  - a public static method named GetUid
- *  - a public method named Print
- *  - a public method named GetSerializedSize
- *  - a public method named Serialize
- *  - a public method named Deserialize
- *
- * So, a tag class should look like this:
- * \code
- * // in header file
- * // note how a tag class does not derive from any other class.
- * class MyTag 
- * {
- * public:
- *   // we need a public default constructor
- *   MyTag ();
- *   // we need a public static GetUid
- *   // GetUid must return a 32 bit integer which uniquely
- *   // identifies this tag type
- *   static uint32_t GetUid (void);
- *   // Print should record in the output stream
- *   // the content of the tag instance.
- *   void Print (std::ostream &os) const;
- *   // GetSerializedSize should return the number of bytes needed
- *   // to store the state of a tag instance
- *   uint32_t GetSerializedSize (void) const;
- *   // Serialize should store its state in the input
- *   // buffer with the help of the iterator. It should
- *   // write exactly size bytes.
- *   void Serialize (Buffer::Iterator i, uint32_t size) const;
- *   // Deserialize should restore the state of a Tag instance
- *   // from a byte buffer with the help of the iterator
- *   uint32_t Deserialize (Buffer::Iterator i);
- * };
- *
- * // in source file
- * 
- * NS_TAG_ENSURE_REGISTERED (MyTag);
- *
- * std::string MyTag::GetUid (void)
- * {
- *   // we really want to make sure that this
- *   // string is unique in the universe.
- *   static uint32_t uid = TagRegistry::Register<MyTag> ("MyTag.unique.prefix");
- *   return uid;
- * }
- * \endcode
- */
-
-/**
  * \defgroup packetperf Packet Performance
  * The current implementation of the byte buffers and tag list is based
  * on COW (Copy On Write. An introduction to COW can be found in Scott 
@@ -416,9 +377,11 @@
 void
 Packet::AddHeader (T const &header)
 {
-  NS_ASSERT_MSG (dynamic_cast<Header const *> (&header) != 0, 
-                 "Must pass Header subclass to Packet::AddHeader");
-  uint32_t size = header.GetSize ();
+  const Header *testHeader;
+  // if the following assignment fails, it is because the 
+  // input to this function is not a subclass of the Header class
+  testHeader = &header;
+  uint32_t size = header.GetSerializedSize ();
   m_buffer.AddAtStart (size);
   header.Serialize (m_buffer.Begin ());
   m_metadata.AddHeader (header, size);
@@ -427,8 +390,10 @@
 uint32_t
 Packet::RemoveHeader (T &header)
 {
-  NS_ASSERT_MSG (dynamic_cast<Header const *> (&header) != 0, 
-                 "Must pass Header subclass to Packet::RemoveHeader");
+  Header *testHeader;
+  // if the following assignment fails, it is because the 
+  // input to this function is not a subclass of the Header class
+  testHeader = &header;
   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
   m_buffer.RemoveAtStart (deserialized);
   m_metadata.RemoveHeader (header, deserialized);
@@ -438,9 +403,11 @@
 void
 Packet::AddTrailer (T const &trailer)
 {
-  NS_ASSERT_MSG (dynamic_cast<Trailer const *> (&trailer) != 0, 
-                 "Must pass Trailer subclass to Packet::AddTrailer");
-  uint32_t size = trailer.GetSize ();
+  const Trailer *testTrailer;
+  // if the following assignment fails, it is because the 
+  // input to this function is not a subclass of the Trailer class
+  testTrailer = &trailer;
+  uint32_t size = trailer.GetSerializedSize ();
   m_buffer.AddAtEnd (size);
   Buffer::Iterator end = m_buffer.End ();
   trailer.Serialize (end);
@@ -450,8 +417,10 @@
 uint32_t
 Packet::RemoveTrailer (T &trailer)
 {
-  NS_ASSERT_MSG (dynamic_cast<Trailer const *> (&trailer) != 0, 
-                 "Must pass Trailer subclass to Packet::RemoveTrailer");
+  Trailer *testTrailer;
+  // if the following assignment fails, it is because the 
+  // input to this function is not a subclass of the Trailer class
+  testTrailer = &trailer;
   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
   m_buffer.RemoveAtEnd (deserialized);
   m_metadata.RemoveTrailer (trailer, deserialized);
@@ -462,18 +431,31 @@
 template <typename T>
 void Packet::AddTag (T const& tag)
 {
+  const Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
   m_tags.Add (tag);
 }
 template <typename T>
 bool Packet::RemoveTag (T & tag)
 {
+  Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
   return m_tags.Remove (tag);
 }
 template <typename T>
 bool Packet::PeekTag (T & tag) const
 {
+  Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
   return m_tags.Peek (tag);
 }
-}; // namespace ns3
+
+} // namespace ns3
 
 #endif /* PACKET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-registry.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,87 @@
+/* -*- 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 "tag-registry.h"
+#include "ns3/fatal-error.h"
+
+namespace ns3 {
+
+TagRegistry::TagInfoVector *
+TagRegistry::GetInfo (void)
+{
+  static TagRegistry::TagInfoVector vector;
+  return &vector;
+}
+
+std::string
+TagRegistry::GetUidString (uint32_t uid)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  return info.uidString;
+}
+uint32_t 
+TagRegistry::GetUidFromUidString (std::string uidString)
+{
+  TagInfoVector *vec = GetInfo ();
+  uint32_t uid = 1;
+  for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+    {
+      if (i->uidString == uidString)
+        {
+          return uid;
+        }
+      uid++;
+    }
+  NS_FATAL_ERROR ("We are trying to deserialize an un-registered type. This can't work.");
+  return 0;
+}
+
+void 
+TagRegistry::Destruct (uint32_t uid, uint8_t *data)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  info.destruct (data);
+}
+void 
+TagRegistry::Print (uint32_t uid, uint8_t *data, std::ostream &os)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  info.print (data, os);
+}
+uint32_t
+TagRegistry::GetSerializedSize (uint32_t uid, uint8_t *data)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  return info.getSerializedSize (data);
+}
+void 
+TagRegistry::Serialize (uint32_t uid, uint8_t *data, Buffer::Iterator start)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  info.serialize (data, start);
+}
+uint32_t 
+TagRegistry::Deserialize (uint32_t uid, uint8_t *data, Buffer::Iterator start)
+{
+  TagInfo info = (*GetInfo ())[uid - 1];
+  return info.deserialize (data, start);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-registry.h	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,149 @@
+/* -*- 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 TAG_REGISTRY_H
+#define TAG_REGISTRY_H
+
+#include <string>
+#include <stdint.h>
+#include "buffer.h"
+
+namespace ns3 {
+
+/**
+ * \brief a registry of all existing tag types.
+ * \internal
+ *
+ * This class is used to give polymorphic access to the methods
+ * exported by a tag. It also is used to associate a single
+ * reliable uid to each unique type. 
+ */
+class TagRegistry
+{
+public:
+  template <typename T>
+  static uint32_t Register (std::string uidString);
+  static std::string GetUidString (uint32_t uid);
+  static uint32_t GetUidFromUidString (std::string uidString);
+  static void Destruct (uint32_t uid, uint8_t *data);
+  static void Print (uint32_t uid, uint8_t *data, std::ostream &os);
+  static uint32_t GetSerializedSize (uint32_t uid, uint8_t *data);
+  static void Serialize (uint32_t uid, uint8_t *data, Buffer::Iterator start);
+  static uint32_t Deserialize (uint32_t uid, uint8_t *data, Buffer::Iterator start);
+private:
+  typedef void (*DestructCb) (uint8_t *);
+  typedef void (*PrintCb) (uint8_t *, std::ostream &);
+  typedef uint32_t (*GetSerializedSizeCb) (uint8_t *);
+  typedef void (*SerializeCb) (uint8_t *, Buffer::Iterator);
+  typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
+  struct TagInfo
+  {
+    std::string uidString;
+    DestructCb destruct;
+    PrintCb print;
+    GetSerializedSizeCb getSerializedSize;
+    SerializeCb serialize;
+    DeserializeCb deserialize;
+  };
+  typedef std::vector<struct TagInfo> TagInfoVector;
+
+  template <typename T>
+  static void DoDestruct (uint8_t *data);
+  template <typename T>
+  static void DoPrint (uint8_t *data, std::ostream &os);
+  template <typename T>
+  static uint32_t DoGetSerializedSize (uint8_t *data);
+  template <typename T>
+  static void DoSerialize (uint8_t *data, Buffer::Iterator start);
+  template <typename T>
+  static uint32_t DoDeserialize (uint8_t *data, Buffer::Iterator start);
+
+  static TagInfoVector *GetInfo (void);
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void 
+TagRegistry::DoDestruct (uint8_t *data)
+{
+  T *tag = reinterpret_cast<T *> (data);
+  tag->~T ();  
+}
+template <typename T>
+void 
+TagRegistry::DoPrint (uint8_t *data, std::ostream &os)
+{
+  T *tag = reinterpret_cast<T *> (data);
+  tag->Print (os);
+}
+template <typename T>
+uint32_t 
+TagRegistry::DoGetSerializedSize (uint8_t *data)
+{
+  T *tag = reinterpret_cast<T *> (data);
+  return tag->GetSerializedSize ();
+}
+template <typename T>
+void 
+TagRegistry::DoSerialize (uint8_t *data, Buffer::Iterator start)
+{
+  T *tag = reinterpret_cast<T *> (data);
+  tag->Serialize (start);
+}
+template <typename T>
+uint32_t 
+TagRegistry::DoDeserialize (uint8_t *data, Buffer::Iterator start)
+{
+  T *tag = reinterpret_cast<T *> (data);
+  return tag->Deserialize (start);
+}
+
+template <typename T>
+uint32_t 
+TagRegistry::Register (std::string uidString)
+{
+  TagInfoVector *vec = GetInfo ();
+  uint32_t j = 0;
+  for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+    {
+      if (i->uidString == uidString)
+        {
+          return j;
+        }
+      j++;
+    }
+  TagInfo info;
+  info.uidString = uidString;
+  info.destruct = &TagRegistry::DoDestruct<T>;
+  info.print = &TagRegistry::DoPrint<T>;
+  info.getSerializedSize = &TagRegistry::DoGetSerializedSize<T>;
+  info.serialize = &TagRegistry::DoSerialize<T>;
+  info.deserialize = &TagRegistry::DoDeserialize<T>;
+  vec->push_back (info);
+  uint32_t uid = vec->size ();
+  return uid;
+}
+
+} // namespace ns3
+
+#endif /* TAG_REGISTRY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag.h	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,126 @@
+/* -*- 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 TAG_H
+#define TAG_H
+
+#include <stdint.h>
+#include <string>
+
+/**
+ * \relates ns3::Tag
+ * \brief this macro should be instantiated exactly once for each
+ *        new type of Tag
+ *
+ * This macro will ensure that your new Tag type is registered
+ * within the tag registry. In most cases, this macro
+ * is not really needed but, for safety, please, use it all the
+ * time.
+ *
+ * Note: This macro is _absolutely_ needed if you try to run a
+ * distributed simulation.
+ */
+#define NS_TAG_ENSURE_REGISTERED(x)	       \
+static class thisisaveryverylongclassname ##x  \
+{					       \
+ public:				       \
+  thisisaveryverylongclassname ##x ()          \
+    { uint32_t uid; uid = x::GetUid ();}       \
+} g_thisisanotherveryveryverylongname ## x;
+
+namespace ns3 {
+
+/**
+ * \brief a tag can be stored in a packet.
+ *
+ * A tag is a blob of 16 bytes of data which can be stored in
+ * a packet: a packet can contain an arbitrary number of tags
+ * and these tags are considered as "on-the-side" per-packet
+ * data structures which are not taken into account when calculating
+ * the size of the payload of a packet. They exist solely as 
+ * simulation-specific objects.
+ *
+ * Tags are typically used to:
+ *   - implement per-packet cross-layer communication
+ *   - implement packet coloring: you could store a "color" tag
+ *     in a packet to mark various types of packet for
+ *     simulation analysis
+ *
+ * To create a new type of tag, you must create a subclass
+ * of the Tag base class which defines:
+ *  - a public default constructor: needed for implementation
+ *    purposes of the Packet code.
+ *  - a public copy constructor: needed to copy a tag into
+ *    a packet tag buffer when the user invokes Packet::AddTag
+ *  - a public destructor: needed to destroy the copy of a tag
+ *    stored in a packet buffer when the user invokes Packet::RemoveTag
+ *    or when the packet is destroyed and the last reference to 
+ *    a tag instance disapears.
+ *  - a public static method named GetUid: needed to uniquely
+ *    the type of each tag instance.
+ *  - a public method named Print: needed to print the content
+ *    of a tag when the user calls Packet::PrintTags
+ *  - a public method named GetSerializedSize: needed to serialize
+ *    the content of a tag to a byte buffer when a packet must
+ *    be sent from one computing node to another in a parallel 
+ *    simulation. If this method returns 0, it means that the
+ *    tag does not need to be transfered from computing node to 
+ *     computing node
+ *  - a public method named Serialize: perform the serialization
+ *    to a byte buffer upon transfer to a new computing node in a 
+ *    parallel simulation.
+ *  - a public method named Deserialize: invert the serialization
+ *    from a byte buffer after being transfered to a new computing
+ *    node in a parallel simulation.
+ *
+ * A detailed example of what these methods should look like
+ * and how they should be implemented is described in samples/main-packet-tag.cc
+ */
+class Tag
+{
+protected:
+  /**
+   * \param name the unique name of the new type of tag
+   * \returns a newly-allocated uid
+   *
+   * This method should be used by subclasses to implement
+   * their static public GetUid method.
+   */
+  template <typename T>
+  static uint32_t AllocateUid (std::string name);
+};
+
+} // namespace ns3
+
+// implementation below.
+#include "tag-registry.h"
+
+namespace ns3 {
+
+template <typename T>
+uint32_t
+Tag::AllocateUid (std::string name)
+{
+  return TagRegistry::Register<T> (name);
+}
+
+} // namespace ns3
+
+#endif /* TAG_H */
--- a/src/common/tags.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/tags.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -24,67 +24,6 @@
 
 namespace ns3 {
 
-TagRegistry::TagInfoVector *
-TagRegistry::GetInfo (void)
-{
-  static TagRegistry::TagInfoVector vector;
-  return &vector;
-}
-
-std::string
-TagRegistry::GetUidString (uint32_t uid)
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  return info.uidString;
-}
-uint32_t 
-TagRegistry::GetUidFromUidString (std::string uidString)
-{
-  TagInfoVector *vec = GetInfo ();
-  uint32_t uid = 1;
-  for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
-    {
-      if (i->uidString == uidString)
-        {
-          return uid;
-        }
-      uid++;
-    }
-  NS_FATAL_ERROR ("We are trying to deserialize an un-registered type. This can't work.");
-  return 0;
-}
-
-void 
-TagRegistry::Destruct (uint32_t uid, uint8_t data[Tags::SIZE])
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  info.destruct (data);
-}
-void 
-TagRegistry::Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os)
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  info.print (data, os);
-}
-uint32_t
-TagRegistry::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE])
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  return info.getSerializedSize (data);
-}
-void 
-TagRegistry::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  info.serialize (data, start);
-}
-uint32_t 
-TagRegistry::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
-{
-  TagInfo info = (*GetInfo ())[uid - 1];
-  return info.deserialize (data, start);
-}
-
 #ifdef USE_FREE_LIST
 
 struct Tags::TagData *Tags::gFree = 0;
@@ -185,6 +124,10 @@
   for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
     {
       TagRegistry::Print (cur->m_id, cur->m_data, os);
+      if (cur->m_next != 0)
+        {
+          os << " ";
+        }
     }
 }
 
@@ -296,10 +239,10 @@
   virtual bool RunTests (void);
 };
 
-class myTagA 
+class myTagA : public Tag
 {
 public:
-  static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagA> ("myTagA.test.nsnam.org"); return uid;}
+  static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<myTagA> ("myTagA.test.nsnam.org"); return uid;}
   void Print (std::ostream &os) const {g_a = true;}
   uint32_t GetSerializedSize (void) const {return 1;}
   void Serialize (Buffer::Iterator i) const {i.WriteU8 (a);}
@@ -307,10 +250,10 @@
 
   uint8_t a;
 };
-class myTagB 
+class myTagB : public Tag
 {
 public:
-  static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagB> ("myTagB.test.nsnam.org"); return uid;}
+  static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<myTagB> ("myTagB.test.nsnam.org"); return uid;}
   void Print (std::ostream &os) const {g_b = true;}
   uint32_t GetSerializedSize (void) const {return 4;}
   void Serialize (Buffer::Iterator i) const {i.WriteU32 (b);}
@@ -318,21 +261,21 @@
 
   uint32_t b;
 };
-class myTagC 
+class myTagC : public Tag
 {
 public:
-  static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagC> ("myTagC.test.nsnam.org"); return uid;}
+  static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<myTagC> ("myTagC.test.nsnam.org"); return uid;}
   void Print (std::ostream &os) const {g_c = true;}
   uint32_t GetSerializedSize (void) const {return Tags::SIZE;}
   void Serialize (Buffer::Iterator i) const {i.Write (c, Tags::SIZE);}
   uint32_t Deserialize (Buffer::Iterator i) {i.Read (c, Tags::SIZE); return Tags::SIZE;}
   uint8_t c [Tags::SIZE];
 };
-class myInvalidTag 
+class myInvalidTag : public Tag
 {
 public:
   static uint32_t GetUid (void) 
-  {static uint32_t uid = TagRegistry::Register<myInvalidTag> ("myinvalidTag.test.nsnam.org"); return uid;}
+  {static uint32_t uid = AllocateUid<myInvalidTag> ("myinvalidTag.test.nsnam.org"); return uid;}
   void Print (std::ostream &os) const {}
   uint32_t GetSerializedSize (void) const {return 0;}
   void Serialize (Buffer::Iterator i) const {}
@@ -340,10 +283,10 @@
 
   uint8_t invalid [Tags::SIZE+1];
 };
-class myTagZ 
+class myTagZ  : public Tag
 {
 public:
-  static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagZ> ("myTagZ.test.nsnam.org"); return uid;}
+  static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<myTagZ> ("myTagZ.test.nsnam.org"); return uid;}
   void Print (std::ostream &os) const {g_z = true;}
   uint32_t GetSerializedSize (void) const {return 0;}
   void Serialize (Buffer::Iterator i) const {}
@@ -352,11 +295,11 @@
   uint8_t z;
 };
 
-class MySmartTag 
+class MySmartTag : public Tag
 {
 public:
   static uint32_t GetUid (void) 
-  {static uint32_t uid = TagRegistry::Register<MySmartTag> ("MySmartTag.test.nsnam.org"); return uid;}
+  {static uint32_t uid = AllocateUid<MySmartTag> ("MySmartTag.test.nsnam.org"); return uid;}
   MySmartTag ()
   {
     //std::cout << "construct" << std::endl;
--- a/src/common/tags.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/tags.h	Thu Aug 09 13:42:42 2007 +0200
@@ -26,35 +26,8 @@
 #include <vector>
 #include "buffer.h"
 
-/**
- * \ingroup tag
- * \brief this macro should be instantiated exactly once for each
- *        new type of Tag
- *
- * This macro will ensure that your new Tag type is registered
- * within the tag registry. In most cases, this macro
- * is not really needed but, for safety, please, use it all the
- * time.
- *
- * Note: This macro is _absolutely_ needed if you try to run a
- * distributed simulation.
- */
-#define NS_TAG_ENSURE_REGISTERED(x)            \
-namespace {                                     \
-static class thisisaveryverylongclassname       \
-{                                               \
-public:                                         \
-  thisisaveryverylongclassname ()               \
-  { uint32_t uid; uid = x::GetUid ();}          \
-} g_thisisanotherveryveryverylongname;          \
-}
-
-
 namespace ns3 {
 
-template <typename T>
-class TagPrettyPrinter;
-
 /**
  * \ingroup constants
  * \brief Tag maximum size
@@ -114,128 +87,22 @@
 /**************************************************************
    An implementation of the templates defined above
  *************************************************************/
+#include "tag-registry.h"
+#include "tag.h"
 #include "ns3/assert.h"
 #include <string>
 
 namespace ns3 {
 
-/**
- * \brief a registry of all existing tag types.
- * \internal
- *
- * This class is used to give polymorphic access to the methods
- * exported by a tag. It also is used to associate a single
- * reliable uid to each unique type. 
- */
-class TagRegistry
-{
-public:
-  template <typename T>
-  static uint32_t Register (std::string uidString);
-  static std::string GetUidString (uint32_t uid);
-  static uint32_t GetUidFromUidString (std::string uidString);
-  static void Destruct (uint32_t uid, uint8_t data[Tags::SIZE]);
-  static void Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os);
-  static uint32_t GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE]);
-  static void Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start);
-  static uint32_t Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start);
-private:
-  typedef void (*DestructCb) (uint8_t [Tags::SIZE]);
-  typedef void (*PrintCb) (uint8_t [Tags::SIZE], std::ostream &);
-  typedef uint32_t (*GetSerializedSizeCb) (uint8_t [Tags::SIZE]);
-  typedef void (*SerializeCb) (uint8_t [Tags::SIZE], Buffer::Iterator);
-  typedef uint32_t (*DeserializeCb) (uint8_t [Tags::SIZE], Buffer::Iterator);
-  struct TagInfo
-  {
-    std::string uidString;
-    DestructCb destruct;
-    PrintCb print;
-    GetSerializedSizeCb getSerializedSize;
-    SerializeCb serialize;
-    DeserializeCb deserialize;
-  };
-  typedef std::vector<struct TagInfo> TagInfoVector;
-
-  template <typename T>
-  static void DoDestruct (uint8_t data[Tags::SIZE]);
-  template <typename T>
-  static void DoPrint (uint8_t data[Tags::SIZE], std::ostream &os);
-  template <typename T>
-  static uint32_t DoGetSerializedSize (uint8_t data[Tags::SIZE]);
-  template <typename T>
-  static void DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
-  template <typename T>
-  static uint32_t DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
-
-  static TagInfoVector *GetInfo (void);
-};
-
-template <typename T>
-void 
-TagRegistry::DoDestruct (uint8_t data[Tags::SIZE])
-{
-  T *tag = reinterpret_cast<T *> (data);
-  tag->~T ();  
-}
-template <typename T>
-void 
-TagRegistry::DoPrint (uint8_t data[Tags::SIZE], std::ostream &os)
-{
-  T *tag = reinterpret_cast<T *> (data);
-  tag->Print (os);
-}
-template <typename T>
-uint32_t 
-TagRegistry::DoGetSerializedSize (uint8_t data[Tags::SIZE])
-{
-  T *tag = reinterpret_cast<T *> (data);
-  return tag->GetSerializedSize ();
-}
-template <typename T>
-void 
-TagRegistry::DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
-{
-  T *tag = reinterpret_cast<T *> (data);
-  tag->Serialize (start);
-}
-template <typename T>
-uint32_t 
-TagRegistry::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
-{
-  T *tag = reinterpret_cast<T *> (data);
-  return tag->Deserialize (start);
-}
-
-template <typename T>
-uint32_t 
-TagRegistry::Register (std::string uidString)
-{
-  TagInfoVector *vec = GetInfo ();
-  uint32_t j = 0;
-  for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
-    {
-      if (i->uidString == uidString)
-        {
-          return j;
-        }
-      j++;
-    }
-  TagInfo info;
-  info.uidString = uidString;
-  info.destruct = &TagRegistry::DoDestruct<T>;
-  info.print = &TagRegistry::DoPrint<T>;
-  info.getSerializedSize = &TagRegistry::DoGetSerializedSize<T>;
-  info.serialize = &TagRegistry::DoSerialize<T>;
-  info.deserialize = &TagRegistry::DoDeserialize<T>;
-  vec->push_back (info);
-  uint32_t uid = vec->size ();
-  return uid;
-}
-
 template <typename T>
 void 
 Tags::Add (T const&tag)
 {
+  const Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
+
   NS_ASSERT (sizeof (T) <= Tags::SIZE);
   // ensure this id was not yet added
   for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
@@ -256,6 +123,10 @@
 bool
 Tags::Remove (T &tag)
 {
+  Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
   NS_ASSERT (sizeof (T) <= Tags::SIZE);
   return Remove (T::GetUid ());
 }
@@ -264,6 +135,10 @@
 bool
 Tags::Peek (T &tag) const
 {
+  Tag *parent;
+  // if the following assignment fails, it is because the
+  // input to this function is not a subclass of the Tag class.
+  parent = &tag;
   NS_ASSERT (sizeof (T) <= Tags::SIZE);
   for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
     {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-context-element.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,34 @@
+#include "trace-context-element.h"
+
+namespace ns3 {
+
+uint32_t 
+ElementRegistry::GetSize (uint16_t uid)
+{
+  InfoVector *vec = GetInfoVector ();
+  struct Info info = (*vec)[uid - 1];
+  return info.size;
+}
+void 
+ElementRegistry::Print (uint16_t uid, uint8_t *instance, std::ostream &os)
+{
+  InfoVector *vec = GetInfoVector ();
+  struct Info info = (*vec)[uid - 1];
+  info.print (instance, os);
+}
+void 
+ElementRegistry::Destroy (uint16_t uid, uint8_t *instance)
+{
+  InfoVector *vec = GetInfoVector ();
+  struct Info info = (*vec)[uid - 1];
+  info.destroy (instance);
+}
+ElementRegistry::InfoVector *
+ElementRegistry::GetInfoVector (void)
+{
+  static InfoVector vector;
+  return &vector;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-context-element.h	Thu Aug 09 13:42:42 2007 +0200
@@ -0,0 +1,189 @@
+#ifndef TRACE_CONTEXT_ELEMENT_H
+#define TRACE_CONTEXT_ELEMENT_H
+
+#include <string>
+#include <vector>
+
+#define NS_TRACE_CONTEXT_ELEMENT_ENSURE_REGISTERED(x)          \
+namespace {						       \
+static class thisisaveryverylongclassname ##x		       \
+  {							       \
+  public:						       \
+    thisisaveryverylongclassname ##x ()			       \
+      { uint32_t uid; uid = x::GetUid ();}		       \
+  } g_thisisanotherveryveryverylongname ##x ;		       \
+}
+
+namespace ns3 {
+
+/**
+ * \brief an item stored in a TraceContext
+ *
+ * To store trace context information in a TraceContext instance,
+ * users must subclass this base class and store subclass instances
+ * in a TraceContext with TraceContext::Add.
+ *
+ * Each subclass should define and implement:
+ *   - a public default constructor: it is used by the internals
+ *     of the implementation of TraceContext.
+ *   - a public destructor: it is also used by the internals of
+ *     the implementation of TraceContext.
+ *   - a public static method named GetUid which returns a 16 bit 
+ *     integer. The integer returned from this method should be
+ *     allocated with the protected AllocatedUid method.
+ *   - a public Print method: this method is used by the 
+ *     TraceContext::Print method to print the content of each
+ *     of the trace context element stored in the trace context.
+ *     This method takes a c++ output stream and argument and is
+ *     expected to write an ascii string describing its content
+ *     in this output stream.
+ *
+ * A typical subclass should look like this:
+ * \code
+ * class MyContext : public TraceContextElement
+ * {
+ * public:
+ *   // the _required_ public API
+ *   static uint16_t GetUid (void);
+ *   MyContext ();
+ *   ~MyContext ();
+ *   void Print (std::ostream &os) const;
+ *
+ *   // the user-specific API to manipulate the context.
+ *   void SetData (uint8_t data);
+ *   uint8_t GetData (void) const;
+ * private:
+ *   uint8_t m_myContextData;
+ * };
+ *
+ * uint16_t 
+ * MyContext::GetUid (void)
+ * {
+ *   static uint16_t uid = AllocateUid<MyContext> ("MyContext");
+ *   return uid;
+ * }
+ * MyContext::MyContext ()
+ * {}
+ * MyContext::~MyContext ()
+ * {}
+ * void 
+ * MyContext::Print (std::ostream &os) const
+ * {
+ *   os << "mycontext=" << (uint32_t) m_myContextData;
+ * }
+ * void 
+ * MyContext::SetData (uint8_t data)
+ * {
+ *   m_myContextData = data;
+ * }
+ * uint8_t 
+ * MyContext::GetData (void) const
+ * {
+ *   return m_myContextData;
+ * }
+ * \endcode
+ */
+class TraceContextElement
+{
+protected:
+  /**
+   * \param name a string which uniquely identifies the type
+   *        of the subclass which is calling this method.
+   * \returns a unique 32 bit integer associated to the
+   *          input string.
+   *
+   * Subclasses are expected to call this method from their
+   * public static GetUid method.
+   */
+  template <typename T>
+  static uint16_t AllocateUid (std::string name);
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+/**
+ * \brief a registry of TraceContextElement subclasses
+ * \internal
+ */
+class ElementRegistry
+{
+public:
+  template <typename T>
+  static uint16_t AllocateUid (std::string name);
+
+  static uint32_t GetSize (uint16_t uid);
+  static void Print (uint16_t uid, uint8_t *instance, std::ostream &os);
+  static void Destroy (uint16_t uid, uint8_t *instance);
+private:
+  typedef void (*PrintCb) (uint8_t *instance, std::ostream &os);
+  typedef void (*DestroyCb) (uint8_t *instance);
+  struct Info {
+    uint32_t size;
+    std::string uidString;
+    PrintCb print;
+    DestroyCb destroy;
+  };
+  typedef std::vector<struct Info> InfoVector;
+  static InfoVector *GetInfoVector (void);
+  template <typename T>
+  static void DoPrint (uint8_t *instance, std::ostream &os);
+  template <typename T>
+  static void DoDestroy (uint8_t *instance);  
+};
+
+template <typename T>
+void 
+ElementRegistry::DoPrint (uint8_t *instance, std::ostream &os)
+{
+  static T obj;
+  // make sure we are aligned.
+  memcpy ((void*)&obj, instance, sizeof (T));
+  obj.Print (os);
+}
+template <typename T>
+void 
+ElementRegistry::DoDestroy (uint8_t *instance)
+{
+  static T obj;
+  // make sure we are aligned.
+  memcpy ((void*)&obj, instance, sizeof (T));
+  obj.~T ();
+}
+
+template <typename T>
+uint16_t 
+ElementRegistry::AllocateUid (std::string name)
+{
+  InfoVector *vec = GetInfoVector ();
+  uint16_t uid = 1;
+  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+    {
+      if (i->uidString == name)
+	{
+	  return uid;
+	}
+      uid++;
+    }
+  struct Info info;
+  info.size = sizeof (T);
+  info.uidString = name;
+  info.print = &ElementRegistry::DoPrint<T>;
+  info.destroy = &ElementRegistry::DoDestroy<T>;
+  vec->push_back (info);
+  return vec->size ();
+}
+
+
+
+template <typename T>
+uint16_t 
+TraceContextElement::AllocateUid (std::string name)
+{
+  return ElementRegistry::AllocateUid<T> (name);
+}
+
+} // namespace ns3
+
+#endif /* TRACE_CONTEXT_ELEMENT_H */
--- a/src/common/trace-context.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/trace-context.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -19,11 +19,11 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "trace-context.h"
+#include "trace-context-element.h"
 #include "ns3/assert.h"
 
 namespace ns3 {
 
-
 TraceContext::TraceContext ()
   : m_data (0)
 {}
@@ -67,19 +67,6 @@
     }
 }
 
-TraceContext::Sizes *
-TraceContext::GetSizes (void)
-{
-  static Sizes sizes;
-  return &sizes;
-}
-
-uint8_t 
-TraceContext::GetSize (uint8_t uid)
-{
-  return (*GetSizes ())[uid];
-}
-
 void 
 TraceContext::Add (TraceContext const &o)
 {
@@ -87,12 +74,12 @@
     {
       return;
     }
-  uint8_t currentUid;
+  uint16_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 size = ElementRegistry::GetSize (currentUid);
       uint8_t *selfBuffer = CheckPresent (currentUid);
       uint8_t *otherBuffer = &(o.m_data->data[i+1]);
       if (selfBuffer != 0)
@@ -122,7 +109,7 @@
   uint16_t i = 0;
   do {
     currentUid = m_data->data[i];
-    uint8_t size = TraceContext::GetSize (currentUid);
+    uint8_t size = ElementRegistry::GetSize (currentUid);
     if (currentUid == uid)
       {
         return &m_data->data[i+1];
@@ -137,7 +124,7 @@
 TraceContext::DoAdd (uint8_t uid, uint8_t const *buffer)
 {
   NS_ASSERT (uid != 0);
-  uint8_t size = TraceContext::GetSize (uid);
+  uint8_t size = ElementRegistry::GetSize (uid);
   uint8_t *present = CheckPresent (uid);
   if (present != 0) {
     if (memcmp (present, buffer, size) == 0)
@@ -207,7 +194,7 @@
   uint16_t i = 0;
   do {
     currentUid = m_data->data[i];
-    uint8_t size = TraceContext::GetSize (currentUid);
+    uint8_t size = ElementRegistry::GetSize (currentUid);
     if (currentUid == uid)
       {
         memcpy (buffer, &m_data->data[i+1], size);
@@ -218,31 +205,48 @@
   return false;
 }
 
-uint8_t
-TraceContext::DoGetNextUid (void)
+void 
+TraceContext::Print (std::ostream &os) const
 {
-  static uint8_t uid = 0;
-  if (uid == 0)
+  if (m_data == 0)
     {
-      GetSizes ()->push_back (0);
+      return;
     }
-  uid++;
-  return uid;
+  uint8_t currentUid;
+  uint16_t i = 0;
+  do {
+    currentUid = m_data->data[i];
+    uint8_t size = ElementRegistry::GetSize (currentUid);
+    uint8_t *instance = &m_data->data[i+1];
+    ElementRegistry::Print (currentUid, instance, os);
+    i += 1 + size;
+    if (i < m_data->size && currentUid != 0)
+      {
+        os << " ";
+      }
+    else
+      {
+        break;
+      }
+  } while (true);
 }
 
-
 }//namespace ns3
 
 #include "ns3/test.h"
+#include <sstream>
 
 namespace ns3 {
 
 template <int N>
-class Ctx
+class Ctx : public TraceContextElement
 {
 public:
+  static uint16_t GetUid (void) {static uint16_t uid = AllocateUid<Ctx<N> > (GetName ()); return uid;}
+  static std::string GetName (void) {std::ostringstream oss; oss << "Ctx" << N; return oss.str ();}
   Ctx () : m_v (0) {}
   Ctx (int v) : m_v (v) {}
+  void Print (std::ostream &os) {os << N;}
   int Get (void) const { return N;}
 private:
   int m_v;
--- a/src/common/trace-context.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/trace-context.h	Thu Aug 09 13:42:42 2007 +0200
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <vector>
 #include "ns3/fatal-error.h"
+#include "trace-context-element.h"
 
 namespace ns3 {
 
@@ -77,26 +78,20 @@
    */
   template <typename T>
   void Get (T &context) const;
+
+  void Print (std::ostream &os) 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);
+  bool SafeAdd (const 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;
 
-  typedef std::vector<uint8_t> Sizes; 
-  static Sizes *GetSizes (void);
   struct Data {
     uint16_t count;
     uint16_t size;
@@ -112,8 +107,12 @@
 void 
 TraceContext::Add (T const &context)
 {
+  const TraceContextElement *parent;
+  // if the following assignment fails, it is because the input
+  // to this function is not a subclass of the TraceContextElement class.
+  parent = &context;
   uint8_t *data = (uint8_t *) &context;
-  bool ok = DoAdd (TraceContext::GetUid<T> (), data);
+  bool ok = DoAdd (T::GetUid (), data);
   if (!ok)
     {
       NS_FATAL_ERROR ("Trying to add twice the same type with different values is invalid.");
@@ -123,8 +122,12 @@
 void
 TraceContext::Get (T &context) const
 {
+  TraceContextElement *parent;
+  // if the following assignment fails, it is because the input
+  // to this function is not a subclass of the TraceContextElement class.
+  parent = &context;
   uint8_t *data = (uint8_t *) &context;
-  bool found = DoGet (TraceContext::GetUid<T> (), data);
+  bool found = DoGet (T::GetUid (), data);
   if (!found)
     {
       NS_FATAL_ERROR ("Type not stored in TraceContext");
@@ -134,35 +137,26 @@
 bool
 TraceContext::SafeGet (T &context) const
 {
+  TraceContextElement *parent;
+  // if the following assignment fails, it is because the input
+  // to this function is not a subclass of the TraceContextElement class.
+  parent = &context;
   uint8_t *data = (uint8_t *) &context;
-  bool found = DoGet (TraceContext::GetUid<T> (), data);
+  bool found = DoGet (T::GetUid (), data);
   return found;
 }
 template <typename T>
 bool
-TraceContext::SafeAdd (T &context)
+TraceContext::SafeAdd (const T &context)
 {
+  const TraceContextElement *parent;
+  // if the following assignment fails, it is because the input
+  // to this function is not a subclass of the TraceContextElement class.
+  parent = &context;
   uint8_t *data = (uint8_t *) &context;
-  bool ok = DoAdd (TraceContext::GetUid<T> (), data);
+  bool ok = DoAdd (T::GetUid (), 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 ();
-  GetSizes ()->push_back (sizeof (T));
-  return uid;
-}
-
 }//namespace ns3
 
 #endif /* TRACE_CONTEXT_H */
--- a/src/common/trace-root.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/trace-root.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -41,7 +41,7 @@
                      Callback<TraceResolver *,TraceContext const &> createResolver)
 {
   CompositeTraceResolver *resolver = GetComposite ();
-  resolver->Add (name, createResolver, TraceRoot::NOTHING);
+  resolver->Add (name, createResolver);
 }
 
 CompositeTraceResolver *
--- a/src/common/trace-root.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/trace-root.h	Thu Aug 09 13:42:42 2007 +0200
@@ -328,9 +328,6 @@
                         Callback<TraceResolver *,TraceContext const &> createResolver);
 private:
   static CompositeTraceResolver *GetComposite (void);
-  enum TraceType {
-    NOTHING,
-  };
 };
 
 }// namespace ns3
--- a/src/common/trailer.cc	Thu Aug 09 13:38:04 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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 "trailer.h"
-
-namespace ns3 {
-
-Trailer::~Trailer ()
-{}
-
-}; // namespace ns3
--- a/src/common/trailer.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/trailer.h	Thu Aug 09 13:42:42 2007 +0200
@@ -22,10 +22,10 @@
 #ifndef TRAILER_H
 #define TRAILER_H
 
-#include "chunk.h"
+#include "chunk-registry.h"
 
 /**
- * \relates Trailer
+ * \relates ns3::Trailer
  * \brief this macro should be instantiated exactly once for each
  *        new type of Trailer
  *
@@ -37,15 +37,13 @@
  * Note: This macro is _absolutely_ needed if you try to run a
  * distributed simulation.
  */
-#define NS_TRAILER_ENSURE_REGISTERED(x)         \
-namespace {                                     \
-static class thisisaveryverylongclassname       \
-{                                               \
-public:                                         \
-  thisisaveryverylongclassname ()               \
-  { uint32_t uid; uid = x::GetUid ();}          \
-} g_thisisanotherveryveryverylongname;          \
-}
+#define NS_TRAILER_ENSURE_REGISTERED(x)          \
+static class thisisaveryverylongclassname ##x    \
+{                                                \
+ public:                                         \
+  thisisaveryverylongclassname ##x ()            \
+    { uint32_t uid; uid = x::GetUid ();}         \
+} g_thisisanotherveryveryverylongname ##x;
 
 namespace ns3 {
 
@@ -53,123 +51,52 @@
  * \brief Protocol trailer serialization and deserialization.
  *
  * Every Protocol trailer which needs to be inserted or removed
- * from a Packet instance must derive from this abstract base class
- * and implement the private pure virtual methods listed below:
- *   - ns3::Trailer::SerializeTo
- *   - ns3::Trailer::DeserializeFrom
- *   - ns3::Trailer::GetSerializedSize
- *   - ns3::Trailer::PrintTo
- *   - ns3::Trailer::DoGetName
- *
- * Each trailer must also make sure that:
- *   - it defines a public default constructor
- *   - it defines a public static method named GetUid which returns a 32 bit integer.
- *
- * The latter should look like the following:
- * \code
- * // in the header
- * class MyTrailer : public Header
- * {
- * public:
- *   static uint32_t GetUid (void);
- * };
- *
- * // in the source file
- * NS_TRAILER_ENSURE_REGISTERED (MyTrailer);
+ * from a Packet instance must derive from this base class and
+ * implement the following public methods:
+ *   - a default constructor: is used by the internal implementation
+ *     if the Packet class.
+ *   - a static method named GetUid: is used to uniquely identify
+ *     the type of each trailer. This method shall return a unique
+ *     integer allocated with Trailer::AllocateUid.
+ *   - a method named Serialize: is used by Packet::AddTrailer to
+ *     store a trailer into the byte buffer of a packet.
+ *     The input iterator points to the end of the byte buffer in
+ *     which the trailer should write its data: the user is thus
+ *     required to call Buffer::Iterator::Prev prior to writing
+ *     any data in the buffer. The data written is expected to 
+ *     match bit-for-bit the representation of this trailer in a 
+ *     real network.
+ *   - a method named GetSerializedSize: is used by Packet::AddTrailer
+ *     to store a trailer into the byte buffer of a packet. This method
+ *     should return the number of bytes which are needed to store
+ *     the full trailer data by Serialize.
+ *   - a method named Deserialize: is used by Packet::RemoveTrailer to
+ *     re-create a trailer from the byte buffer of a packet. The input
+ *     iterator points to the end of the byte buffer from which
+ *     the trailer should read its data: the user is thus required to
+ *     call Buffer::Iterator::Prev prior to reading any data from the
+ *     buffer. The data read is expected to match bit-for-bit the 
+ *     representation of this trailer in real networks. This method 
+ *     shall return an integer which identifies the number of bytes read.
+ *   - a method named Print: is used by Packet::Print to print the 
+ *     content of a trailer as ascii data to a c++ output stream.
+ *     Although the trailer is free to format its output as it
+ *     wishes, it is recommended to follow a few rules to integrate
+ *     with the packet pretty printer: start with flags, small field 
+ *     values located between a pair of parens. Values should be separated 
+ *     by whitespace. Follow the parens with the important fields, 
+ *     separated by whitespace.
+ *     i.e.: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
+ *   - a method named GetName: is used by Packet::Print to print
+ *     trailer fragments. This method should return a user-readable
+ *     single word as all capitalized letters.
  *
- * uint32_t MyTrailer::GetUid (void)
- * {
- *   static uint32_t uid = Trailer::Register<MyTrailer> ("MyTrailer.unique.prefix");
- *   return uid;
- * }
- * \endcode
- *
- * Note that the SerializeTo and DeserializeFrom methods behave
- * in a way which might seem surprising to users: the input iterator
- * really points to the end of the buffer to which and from which
- * the user is expected to write and read respectively. This means that
- * if the trailer has a fixed size and if the user wishes to read or
- * write that trailer from front to back, the user must rewind the 
- * iterator by hand to go to the start of the trailer. Typical code
- * looks like this:
- * \code
- * void CrcTrailer::SerializeTo (Buffer::Iterator end)
- * {
- *   end.Prev (4);
- *   end.WriteHtonU32 (m_crc);
- * }
- * \endcode
- *
- * Some users would have expected that the iterator would be rewinded 
- * to the "start" of the trailer before calling SerializeTo and DeserializeFrom.
- * However, this behavior was not implemented because it cannot be made to
- * work reliably for trailers which have a variable size. i.e., if the trailer 
- * contains options, the code which calls DeserializeFrom cannot rewind
- * to the start of the trailer because it does not know the real size of the 
- * trailer. Hence, to make this legitimate use-case work (variable-sized 
- * trailers), the input iterator to DeserializeFrom and SerializeTo points
- * to the end of the trailer, and not its start.
  */
-class Trailer : public Chunk {
-public:
-  virtual ~Trailer ();
+class Trailer 
+{
 protected:
   template <typename T>
-  static uint32_t Register (std::string uidString);
-private:
-  /**
-   * \returns a user-readable name to identify this type of header.
-   *
-   * The string returned is expected to be a single word with 
-   * all capital letters
-   */
-  virtual std::string DoGetName (void) const = 0;
-  /**
-   * \param os the std output stream in which this 
-   *       protocol trailer must print itself.
-   *
-   * Although the header is free to format its output as it
-   * wishes, it is recommended to follow a few rules to integrate
-   * with the packet pretty printer:
-   *   - start with flags, small field values located between a
-   *     pair of parens. Values should be separated by whitespace.
-   *   - follow the parens with the important fields, separated by
-   *     whitespace.
-   * i.e.:
-   * (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
-   */
-  virtual void PrintTo (std::ostream &os) const = 0;
-
-  /**
-   * \returns the size of the serialized Trailer.
-   *
-   * This method is used by Packet::AddTrailer to reserve
-   * enough room in the packet byte buffer prior to calling
-   * Trailer::Serialize.
-   */
-  virtual uint32_t GetSerializedSize (void) const = 0;
-
-  /**
-   * \param end the buffer iterator in which the protocol trailer
-   *    must serialize itself. This iterator identifies 
-   *    the end of the buffer.
-   *
-   * This iterator must be typically moved with the Buffer::Iterator::Prev
-   * method before writing any byte in the buffer.
-   */
-  virtual void SerializeTo (Buffer::Iterator end) const = 0;
-  /**
-   * \param end the buffer iterator from which the protocol trailer must
-   *    deserialize itself. This iterator identifies 
-   *    the end of the buffer.
-   * \returns the number of bytes read from the buffer
-   *
-   * This iterator must be typically moved with the Buffer::Iterator::Prev
-   * method before reading any byte in the buffer. The value returned
-   * is used to trim the packet byte buffer of the corresponding
-   * amount when this method is invoked from Packet::RemoveTrailer
-   */
-  virtual uint32_t DeserializeFrom (Buffer::Iterator end) = 0;
+  static uint32_t AllocateUid (std::string uidString);
 };
 
 } // namespace ns3
@@ -178,7 +105,7 @@
 
 template <typename T>
 uint32_t 
-Trailer::Register (std::string uidString)
+Trailer::AllocateUid (std::string uidString)
 {
   return ChunkRegistry::RegisterTrailer<T> (uidString);
 }
--- a/src/common/wscript	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/common/wscript	Thu Aug 09 13:42:42 2007 +0200
@@ -4,17 +4,17 @@
     common = bld.create_ns3_module('common', ['core', 'simulator'])
     common.source = [
         'buffer.cc',
-        'chunk.cc',
-        'header.cc',
-        'trailer.cc',
+        'chunk-registry.cc',
         'packet-printer.cc',
         'packet-metadata.cc',
         'packet-metadata-test.cc',
         'packet.cc',
         'tags.cc',
+        'tag-registry.cc',
         'pcap-writer.cc',
         'variable-tracer-test.cc',
         'trace-context.cc',
+        'trace-context-element.cc',
         'trace-resolver.cc',
         'callback-trace-source.cc',
         'empty-trace-resolver.cc',
@@ -26,10 +26,12 @@
     headers = bld.create_obj('ns3header')
     headers.source = [
         'buffer.h',
-        'chunk.h',
+        'chunk-registry.h',
         'header.h',
         'trailer.h',
         'tags.h',
+        'tag-registry.h',
+        'tag.h',
         'packet.h',
         'packet-printer.h',
         'packet-metadata.h',
@@ -39,6 +41,7 @@
         'pcap-writer.h',
         'callback-trace-source.h',
         'trace-context.h',
+        'trace-context-element.h',
         'trace-resolver.h',
         'empty-trace-resolver.h',
         'composite-trace-resolver.h',
--- a/src/core/assert.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/core/assert.h	Thu Aug 09 13:42:42 2007 +0200
@@ -28,6 +28,17 @@
 #include "breakpoint.h"
 
 /**
+ * \defgroup assert Assert
+ * \brief assert functions and macros
+ *
+ * The assert macros are used to verify
+ * at runtime that a certain condition is true. If it is
+ * not true, the program halts. These checks are built
+ * into the program only in debugging builds. They are
+ * removed in optimized builds.
+ */
+
+/**
  * \ingroup assert
  * \param condition condition to verifiy.
  *
--- a/src/core/callback.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/core/callback.h	Thu Aug 09 13:42:42 2007 +0200
@@ -358,7 +358,7 @@
 
 /**
  * \ingroup MakeCallback
- * \param mem_ptr class method member pointer
+ * \param memPtr class method member pointer
  * \param objPtr class instance
  * \return a wrapper Callback
  * Build Callbacks for class method members which takes no arguments
--- a/src/core/component-manager.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/core/component-manager.h	Thu Aug 09 13:42:42 2007 +0200
@@ -348,7 +348,7 @@
    * result.
    */
   template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-  static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4, T5);
+  static Ptr<T> Create (ClassId classId, InterfaceId iid, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
 
 private:
   friend void RegisterCallback (ClassId classId, CallbackBase *callback, 
--- a/src/core/random-variable.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/core/random-variable.h	Thu Aug 09 13:42:42 2007 +0200
@@ -772,6 +772,7 @@
   /**
    * \param s Low end of the range
    * \param l High end of the range
+   * \param mean mean of the distribution
    * \return A triangularly distributed random number between s and l
    */
   static double GetSingleValue(double s, double l, double mean);
--- a/src/devices/csma-cd/csma-cd-net-device.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-net-device.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -35,6 +35,32 @@
 
 namespace ns3 {
 
+CsmaCdTraceType::CsmaCdTraceType (enum Type type)
+  : m_type (type)
+{}
+CsmaCdTraceType::CsmaCdTraceType ()
+  : m_type (RX)
+{}
+void 
+CsmaCdTraceType::Print (std::ostream &os) const
+{
+  switch (m_type) {
+  case RX:
+    os << "dev-rx";
+    break;
+  case DROP:
+    os << "dev-drop";
+    break;
+  }
+}
+uint16_t 
+CsmaCdTraceType::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<CsmaCdTraceType> ("CsmaCdTraceType");
+  return uid;
+}
+
+
 CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node)
   : NetDevice (node, Eui48Address::Allocate ()),
     m_bps (DataRate (0xffffffff))
@@ -177,7 +203,7 @@
   switch (m_encapMode) 
     {
     case ETHERNET_V1:
-      lengthType = p.GetSize() + header.GetSize() + trailer.GetSize();
+      lengthType = p.GetSize() + header.GetSerializedSize() + trailer.GetSerializedSize();
       break;
     case IP_ARP:
       lengthType = protocolNumber;
@@ -429,12 +455,14 @@
   CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
   resolver->Add ("queue", 
                  MakeCallback (&Queue::CreateTraceResolver, 
-                               PeekPointer (m_queue)),
-                 CsmaCdNetDevice::QUEUE);
+                               PeekPointer (m_queue)));
   resolver->Add ("rx",
                  m_rxTrace,
-                 CsmaCdNetDevice::RX);
-  return resolver;
+                 CsmaCdTraceType (CsmaCdTraceType::RX));
+  resolver->Add ("drop",
+                 m_dropTrace,
+                 CsmaCdTraceType (CsmaCdTraceType::DROP));
+   return resolver;
 }
 
 bool
--- a/src/devices/csma-cd/csma-cd-net-device.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/devices/csma-cd/csma-cd-net-device.h	Thu Aug 09 13:42:42 2007 +0200
@@ -41,6 +41,21 @@
 class Queue;
 class CsmaCdChannel;
 
+class CsmaCdTraceType : public TraceContextElement
+{
+public:
+  enum Type {
+    RX, 
+    DROP
+  };
+  CsmaCdTraceType (enum Type type);
+  CsmaCdTraceType ();
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+private:
+  enum Type m_type;
+};
+
 /**
  * \class CsmaCdNetDevice
  * \brief A Device for a CsmaCd Network Link.
@@ -62,15 +77,6 @@
  */
 class CsmaCdNetDevice : public NetDevice {
 public:
-  /**
-   * Enumeration of the types of traces supported in the class.
-   *
-   */
-  enum TraceType {
-    QUEUE, /**< Trace queue events on the attached queue */
-    RX,    /**< Trace packet reception events (from the channel) */
-    DROP    /**< Trace packet drop events (from the channel) */
-  };
 
   /**
    * Enumeration of the types of packets supported in the class.
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -40,6 +40,21 @@
            "The default data rate for point to point links",
            DataRate ("10Mb/s"));
 
+PointToPointTraceType::PointToPointTraceType ()
+{}
+void 
+PointToPointTraceType::Print (std::ostream &os) const
+{
+  os << "dev-rx";
+}
+uint16_t 
+PointToPointTraceType::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<PointToPointTraceType> ("PointToPointTraceType");
+  return uid;
+}
+
+
 PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
                                               const DataRate& rate) 
 : 
@@ -178,11 +193,10 @@
 {
   CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
   resolver->Add ("queue", 
-                 MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)),
-                 PointToPointNetDevice::QUEUE);
+                 MakeCallback (&Queue::CreateTraceResolver, PeekPointer (m_queue)));
   resolver->Add ("rx",
                  m_rxTrace,
-                 PointToPointNetDevice::RX);
+                 PointToPointTraceType ());
   return resolver;
 }
 
--- a/src/devices/point-to-point/point-to-point-net-device.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Thu Aug 09 13:42:42 2007 +0200
@@ -38,6 +38,14 @@
 class Queue;
 class PointToPointChannel;
 
+class PointToPointTraceType : public TraceContextElement
+{
+public:
+  PointToPointTraceType ();
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+};
+
 /**
  * \class PointToPointNetDevice
  * \brief A Device for a Point to Point Network Link.
@@ -64,14 +72,6 @@
 class PointToPointNetDevice : public NetDevice {
 public:
   /**
-   * Enumeration of the types of traces supported in the class.
-   *
-   */
-  enum TraceType {
-    QUEUE, /**< Trace queue events on the attached queue */
-    RX,    /**< Trace packet reception events (from the channel) */
-  };
-  /**
    * Construct a PointToPointNetDevice
    *
    * This is the constructor for the PointToPointNetDevice.  It takes as a
--- a/src/internet-node/arp-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/arp-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -23,20 +23,17 @@
 #include "ns3/address-utils.h"
 #include "arp-header.h"
 
-NS_HEADER_ENSURE_REGISTERED (ns3::ArpHeader);
+namespace ns3 {
 
-namespace ns3 {
+NS_HEADER_ENSURE_REGISTERED (ArpHeader);
 
 uint32_t
 ArpHeader::GetUid (void)
 {
-  static uint32_t uid = Header::Register<ArpHeader> ("ArpHeader.ns3");
+  static uint32_t uid = AllocateUid<ArpHeader> ("ArpHeader.ns3");
   return uid;
 }
 
-ArpHeader::~ArpHeader ()
-{}
-
 void 
 ArpHeader::SetRequest (Address sourceHardwareAddress,
                        Ipv4Address sourceProtocolAddress,
@@ -93,13 +90,13 @@
 }
 
 std::string 
-ArpHeader::DoGetName (void) const
+ArpHeader::GetName (void) const
 {
   return "ARP";
 }
 
 void 
-ArpHeader::PrintTo (std::ostream &os) const
+ArpHeader::Print (std::ostream &os) const
 {
   if (IsRequest ()) 
     {
@@ -132,7 +129,7 @@
 }
 
 void
-ArpHeader::SerializeTo (Buffer::Iterator start) const
+ArpHeader::Serialize (Buffer::Iterator start) const
 {
   Buffer::Iterator i = start;
   NS_ASSERT (m_macSource.GetLength () == m_macDest.GetLength ());
@@ -150,7 +147,7 @@
   WriteTo (i, m_ipv4Dest);
 }
 uint32_t
-ArpHeader::DeserializeFrom (Buffer::Iterator start)
+ArpHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
   i.Next (2+2);
--- a/src/internet-node/arp-header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/arp-header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -36,8 +36,6 @@
 public:
   static uint32_t GetUid (void);
 
-  virtual ~ArpHeader ();
-
   void SetRequest (Address sourceHardwareAddress,
                    Ipv4Address sourceProtocolAddress,
                    Address destinationHardwareAddress,
@@ -53,25 +51,11 @@
   Ipv4Address GetSourceIpv4Address (void);
   Ipv4Address GetDestinationIpv4Address (void);
 
-private:
-  virtual std::string DoGetName (void) const;
-  /**
-   * \param os
-   */
-  virtual void PrintTo (std::ostream &os) const;
-  /**
-   * \return
-   */
-  virtual uint32_t GetSerializedSize (void) const;
-  /**
-   * \param start
-   */
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  /**
-   * \param start
-   * \return
-   */
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 
   enum ArpType_e {
     ARP_TYPE_REQUEST = 1,
--- a/src/internet-node/arp-ipv4-interface.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/arp-ipv4-interface.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -47,8 +47,7 @@
   if (GetDevice () != 0)
     {
       resolver->Add ("netdevice",
-                     MakeCallback (&NetDevice::CreateTraceResolver, PeekPointer (GetDevice ())),
-                     ArpIpv4Interface::NETDEVICE);
+                     MakeCallback (&NetDevice::CreateTraceResolver, PeekPointer (GetDevice ())));
     }
   
   return resolver;
--- a/src/internet-node/arp-ipv4-interface.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/arp-ipv4-interface.h	Thu Aug 09 13:42:42 2007 +0200
@@ -39,10 +39,6 @@
 class ArpIpv4Interface : public Ipv4Interface
 {
  public:
-  enum TraceType {
-    NETDEVICE,
-    ARP,
-  };
   ArpIpv4Interface (Ptr<Node> node, Ptr<NetDevice> device);
   virtual ~ArpIpv4Interface ();
 
--- a/src/internet-node/ascii-trace.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ascii-trace.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -24,8 +24,7 @@
 #include "ns3/trace-root.h"
 #include "ns3/simulator.h"
 #include "ns3/node.h"
-#include "ns3/queue.h"
-#include "ns3/node-list.h"
+#include "ns3/packet.h"
 
 namespace ns3 {
 
@@ -55,42 +54,18 @@
 void 
 AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &packet)
 {
-  enum Queue::TraceType type;
-  context.Get (type);
-  switch (type) 
-    {
-    case Queue::ENQUEUE:
-      m_os << "+ ";
-      break;
-    case Queue::DEQUEUE:
-      m_os << "- ";
-      break;
-    case Queue::DROP:
-      m_os << "d ";
-      break;
-    }
   m_os << Simulator::Now ().GetSeconds () << " ";
-  NodeList::NodeIndex nodeIndex;
-  context.Get (nodeIndex);
-  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Node::NetDeviceIndex deviceIndex;
-  context.Get (deviceIndex);
-  m_os << "device=" << deviceIndex << " ";
-  m_os << "pkt-uid=" << packet.GetUid () << " ";
+  context.Print (m_os);
+  m_os << " pkt-uid=" << packet.GetUid () << " ";
   packet.Print (m_os);
   m_os << std::endl;
 }
 void 
 AsciiTrace::LogDevRx (TraceContext const &context, Packet &p)
 {
-  m_os << "r " << Simulator::Now ().GetSeconds () << " ";
-  NodeList::NodeIndex nodeIndex;
-  context.Get (nodeIndex);
-  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Node::NetDeviceIndex deviceIndex;
-  context.Get (deviceIndex);
-  m_os << "device=" << deviceIndex << " ";
-  m_os << "pkt-uid=" << p.GetUid () << " ";
+  m_os << Simulator::Now ().GetSeconds () << " ";
+  context.Print (m_os);
+  m_os << " pkt-uid=" << p.GetUid () << " ";
   p.Print (m_os);
   m_os << std::endl;  
 }
--- a/src/internet-node/internet-node.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/internet-node.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -80,8 +80,7 @@
   Node::DoFillTraceResolver (resolver);
   Ptr<Ipv4L3Protocol> ipv4 = QueryInterface<Ipv4L3Protocol> (Ipv4L3Protocol::iid);
   resolver.Add ("ipv4",
-                MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4)),
-                InternetNode::IPV4);
+                MakeCallback (&Ipv4L3Protocol::CreateTraceResolver, PeekPointer (ipv4)));
 }
 
 void 
--- a/src/internet-node/internet-node.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/internet-node.h	Thu Aug 09 13:42:42 2007 +0200
@@ -36,9 +36,6 @@
 class InternetNode : public Node 
 {
 public:
-  enum TraceType {
-    IPV4,
-  };
   InternetNode();
   InternetNode(uint32_t systemId);
   virtual ~InternetNode ();
--- a/src/internet-node/ipv4-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -26,16 +26,16 @@
 
 NS_DEBUG_COMPONENT_DEFINE ("Ipv4Header");
 
-NS_HEADER_ENSURE_REGISTERED (ns3::Ipv4Header);
+namespace ns3 {
 
-namespace ns3 {
+NS_HEADER_ENSURE_REGISTERED (Ipv4Header);
 
 bool Ipv4Header::m_calcChecksum = false;
 
 uint32_t
 Ipv4Header::GetUid (void)
 {
-  static uint32_t uid = Header::Register<Ipv4Header> ("Ipv4Header.ns3");
+  static uint32_t uid = AllocateUid<Ipv4Header> ("Ipv4Header.ns3");
   return uid;
 }
 
@@ -49,8 +49,6 @@
     m_fragmentOffset (0),
     m_goodChecksum (true)
 {}
-Ipv4Header::~Ipv4Header ()
-{}
 
 void 
 Ipv4Header::EnableChecksums (void)
@@ -189,13 +187,13 @@
 }
 
 std::string 
-Ipv4Header::DoGetName (void) const
+Ipv4Header::GetName (void) const
 {
   return "IPV4";
 }
 
 void 
-Ipv4Header::PrintTo (std::ostream &os) const
+Ipv4Header::Print (std::ostream &os) const
 {
   // ipv4, right ?
   std::string flags;
@@ -238,7 +236,7 @@
 }
 
 void
-Ipv4Header::SerializeTo (Buffer::Iterator start) const
+Ipv4Header::Serialize (Buffer::Iterator start) const
 {
   Buffer::Iterator i = start;
   
@@ -281,7 +279,7 @@
     }
 }
 uint32_t
-Ipv4Header::DeserializeFrom (Buffer::Iterator start)
+Ipv4Header::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
   uint8_t verIhl = i.ReadU8 ();
--- a/src/internet-node/ipv4-header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -37,7 +37,6 @@
    * \brief Construct a null IPv4 header
    */
   Ipv4Header ();
-  virtual ~Ipv4Header ();
   /**
    * \brief Enable checksum calculation for IP (XXX currently has no effect)
    */
@@ -141,12 +140,12 @@
    */
   bool IsChecksumOk (void) const;
 
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
 
   enum FlagsE {
     DONT_FRAGMENT = (1<<0),
@@ -167,7 +166,7 @@
   bool m_goodChecksum;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 
 #endif /* IPV4_HEADER_H */
--- a/src/internet-node/ipv4-l3-protocol.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-l3-protocol.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -44,6 +44,76 @@
 const InterfaceId Ipv4L3Protocol::iid = MakeInterfaceId ("Ipv4L3Protocol", Object::iid);
 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
 
+Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement ()
+  : m_type (TX)
+{}
+Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement (enum Type type)
+  : m_type (type)
+{}
+bool 
+Ipv4L3ProtocolTraceContextElement::IsTx (void) const
+{
+  return m_type == TX;
+}
+bool 
+Ipv4L3ProtocolTraceContextElement::IsRx (void) const
+{
+  return m_type == RX;
+}
+bool 
+Ipv4L3ProtocolTraceContextElement::IsDrop (void) const
+{
+  return m_type == DROP;
+}
+void 
+Ipv4L3ProtocolTraceContextElement::Print (std::ostream &os) const
+{
+  os << "ipv4=";
+  switch (m_type)
+    {
+    case TX:
+      os << "tx";
+      break;
+    case RX:
+      os << "rx";
+      break;
+    case DROP:
+      os << "drop";
+      break;
+    }
+}
+uint16_t 
+Ipv4L3ProtocolTraceContextElement::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<Ipv4L3ProtocolTraceContextElement> ("Ipv4L3ProtocolTraceContextElement");
+  return uid;
+}
+
+
+Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex ()
+  : m_index (0)
+{}
+Ipv4l3ProtocolInterfaceIndex::Ipv4l3ProtocolInterfaceIndex (uint32_t index)
+  : m_index (index)
+{}
+uint32_t 
+Ipv4l3ProtocolInterfaceIndex::Get (void) const
+{
+  return m_index;
+}
+void 
+Ipv4l3ProtocolInterfaceIndex::Print (std::ostream &os) const
+{
+  os << "ipv4-interface=" << m_index;
+}
+uint16_t 
+Ipv4l3ProtocolInterfaceIndex::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<Ipv4l3ProtocolInterfaceIndex> ("Ipv4l3ProtocolInterfaceIndex");
+  return uid;
+}
+
+
 Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
   : m_nInterfaces (0),
     m_defaultTtl (64),
@@ -87,20 +157,19 @@
 Ipv4L3Protocol::CreateTraceResolver (TraceContext const &context)
 {
   CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
-  resolver->Add ("tx", m_txTrace, Ipv4L3Protocol::TX);
-  resolver->Add ("rx", m_rxTrace, Ipv4L3Protocol::RX);
-  resolver->Add ("drop", m_dropTrace, Ipv4L3Protocol::DROP);
+  resolver->Add ("tx", m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX));
+  resolver->Add ("rx", m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX));
+  resolver->Add ("drop", m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP));
   resolver->Add ("interfaces", 
-                 MakeCallback (&Ipv4L3Protocol::InterfacesCreateTraceResolver, this), 
-                 Ipv4L3Protocol::INTERFACES);
+                 MakeCallback (&Ipv4L3Protocol::InterfacesCreateTraceResolver, this));
   return resolver;
 }
 
 TraceResolver *
 Ipv4L3Protocol::InterfacesCreateTraceResolver (TraceContext const &context) const
 {
-  ArrayTraceResolver<Ipv4Interface *> *resolver = 
-    new ArrayTraceResolver<Ipv4Interface *> 
+  ArrayTraceResolver<Ipv4Interface *, Ipv4l3ProtocolInterfaceIndex> *resolver = 
+    new ArrayTraceResolver<Ipv4Interface *,Ipv4l3ProtocolInterfaceIndex> 
     (context,
      MakeCallback (&Ipv4L3Protocol::GetNInterfaces, this),
      MakeCallback (&Ipv4L3Protocol::GetInterface, this));
--- a/src/internet-node/ipv4-l3-protocol.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-l3-protocol.h	Thu Aug 09 13:42:42 2007 +0200
@@ -25,11 +25,11 @@
 #include <list>
 #include <stdint.h>
 #include "ns3/callback-trace-source.h"
-#include "ns3/array-trace-resolver.h"
+#include "ns3/trace-context-element.h"
 #include "ns3/ipv4-address.h"
-#include "ipv4-header.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
+#include "ipv4-header.h"
 #include "ipv4-static-routing.h"
 
 namespace ns3 {
@@ -44,6 +44,37 @@
 class TraceResolver;
 class TraceContext;
 
+class Ipv4L3ProtocolTraceContextElement : public TraceContextElement
+{
+public:
+  enum Type {
+    TX,
+    RX,
+    DROP,
+  };
+  Ipv4L3ProtocolTraceContextElement ();
+  Ipv4L3ProtocolTraceContextElement (enum Type type);
+  bool IsTx (void) const;
+  bool IsRx (void) const;
+  bool IsDrop (void) const;
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+private:
+  enum Type m_type;
+};
+
+class Ipv4l3ProtocolInterfaceIndex : public TraceContextElement
+{
+public:
+  Ipv4l3ProtocolInterfaceIndex ();
+  Ipv4l3ProtocolInterfaceIndex (uint32_t index);
+  uint32_t Get (void) const;
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+private:
+  uint32_t m_index;
+};
+
 
 class Ipv4L3Protocol : public Object
 {
@@ -51,14 +82,6 @@
   static const InterfaceId iid;
   static const uint16_t PROT_NUMBER;
 
-  enum TraceType {
-    TX,
-    RX,
-    DROP,
-    INTERFACES,
-  };
-  typedef ArrayTraceResolver<Ipv4Interface *>::Index InterfaceIndex;
-
   Ipv4L3Protocol(Ptr<Node> node);
   virtual ~Ipv4L3Protocol ();
 
--- a/src/internet-node/ipv4-l4-demux.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-l4-demux.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -32,6 +32,30 @@
 
 const InterfaceId Ipv4L4Demux::iid = MakeInterfaceId ("Ipv4L4Demux", Object::iid);
 
+Ipv4L4ProtocolTraceContextElement::Ipv4L4ProtocolTraceContextElement ()
+  : m_protocolNumber (0)
+{}
+Ipv4L4ProtocolTraceContextElement::Ipv4L4ProtocolTraceContextElement (int protocolNumber)
+  : m_protocolNumber (protocolNumber)
+{}
+int 
+Ipv4L4ProtocolTraceContextElement::Get (void) const
+{
+  return m_protocolNumber;
+}
+void 
+Ipv4L4ProtocolTraceContextElement::Print (std::ostream &os) const
+{
+  os << "ipv4-protocol=0x" << std::hex << m_protocolNumber << std::dec;
+}
+uint16_t 
+Ipv4L4ProtocolTraceContextElement::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<Ipv4L4ProtocolTraceContextElement> ("Ipv4L4ProtocolTraceContextElement");
+  return uid;
+}
+
+
 Ipv4L4Demux::Ipv4L4Demux (Ptr<Node> node)
   : m_node (node)
 {
@@ -64,7 +88,7 @@
       std::string protValue;
       std::ostringstream oss (protValue);
       oss << (*i)->GetProtocolNumber ();
-      Ipv4L4ProtocolTraceType protocolNumber = (*i)->GetProtocolNumber ();
+      Ipv4L4ProtocolTraceContextElement protocolNumber = (*i)->GetProtocolNumber ();
       resolver->Add (protValue,
                      MakeCallback (&Ipv4L4Protocol::CreateTraceResolver, PeekPointer (protocol)),
                      protocolNumber);
--- a/src/internet-node/ipv4-l4-demux.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/ipv4-l4-demux.h	Thu Aug 09 13:42:42 2007 +0200
@@ -28,6 +28,7 @@
 #include <list>
 #include "ns3/object.h"
 #include "ns3/ptr.h"
+#include "ns3/trace-context-element.h"
 
 namespace ns3 {
 
@@ -36,6 +37,18 @@
 class TraceResolver;
 class TraceContext;
 
+class Ipv4L4ProtocolTraceContextElement : public TraceContextElement
+{
+public:
+  Ipv4L4ProtocolTraceContextElement ();
+  Ipv4L4ProtocolTraceContextElement (int protocolNumber);
+  int Get (void) const;
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+private:
+  int m_protocolNumber;
+};
+
 /**
  * \brief L4 Ipv4 Demux
  */
@@ -43,7 +56,6 @@
 {
 public:
   static const InterfaceId iid;
-  typedef int Ipv4L4ProtocolTraceType;
   Ipv4L4Demux (Ptr<Node> node);
   virtual ~Ipv4L4Demux();
 
--- a/src/internet-node/pcap-trace.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/pcap-trace.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -82,10 +82,9 @@
 void 
 PcapTrace::LogIp (TraceContext const &context, Packet const &p, uint32_t interfaceIndex)
 {
-  NodeList::NodeIndex nodeIndex;
+  NodeListIndex nodeIndex;
   context.Get (nodeIndex);
-  uint32_t nodeId = NodeList::GetNode (nodeIndex)->GetId ();
-  PcapWriter *writer = GetStream (nodeId, interfaceIndex);
+  PcapWriter *writer = GetStream (nodeIndex.Get (), interfaceIndex);
   writer->WritePacket (p);
 }
 
--- a/src/internet-node/udp-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/udp-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -22,16 +22,16 @@
 #include "udp-header.h"
 #include "ipv4-checksum.h"
 
-NS_HEADER_ENSURE_REGISTERED (ns3::UdpHeader);
+namespace ns3 {
 
-namespace ns3 {
+NS_HEADER_ENSURE_REGISTERED (UdpHeader);
 
 bool UdpHeader::m_calcChecksum = false;
 
 uint32_t
 UdpHeader::GetUid (void)
 {
-  static uint32_t uid = Header::Register<UdpHeader> ("UdpHeader.ns3");
+  static uint32_t uid = AllocateUid<UdpHeader> ("UdpHeader.ns3");
   return uid;
 }
 
@@ -93,7 +93,7 @@
   destination.Serialize (buf+4);
   buf[8] = 0;
   buf[9] = protocol;
-  uint16_t udpLength = m_payloadSize + GetSize ();
+  uint16_t udpLength = m_payloadSize + GetSerializedSize ();
   buf[10] = udpLength >> 8;
   buf[11] = udpLength & 0xff;
 
@@ -101,16 +101,16 @@
 }
 
 std::string 
-UdpHeader::DoGetName (void) const
+UdpHeader::GetName (void) const
 {
   return "UDP";
 }
 
 void 
-UdpHeader::PrintTo (std::ostream &os) const
+UdpHeader::Print (std::ostream &os) const
 {
   os << "(" 
-     << "length: " << m_payloadSize + GetSize ()
+     << "length: " << m_payloadSize + GetSerializedSize ()
      << ") "
      << m_sourcePort << " > " << m_destinationPort
     ;
@@ -123,12 +123,12 @@
 }
 
 void
-UdpHeader::SerializeTo (Buffer::Iterator start) const
+UdpHeader::Serialize (Buffer::Iterator start) const
 {
   Buffer::Iterator i = start;
   i.WriteHtonU16 (m_sourcePort);
   i.WriteHtonU16 (m_destinationPort);
-  i.WriteHtonU16 (m_payloadSize + GetSize ());
+  i.WriteHtonU16 (m_payloadSize + GetSerializedSize ());
   i.WriteU16 (0);
 
   if (m_calcChecksum) 
@@ -137,7 +137,7 @@
       //XXXX
       uint16_t checksum = Ipv4ChecksumCalculate (m_initialChecksum, 
                                                   buffer->PeekData (), 
-                                                  GetSize () + m_payloadSize);
+                                                  GetSerializedSize () + m_payloadSize);
       checksum = Ipv4ChecksumComplete (checksum);
       i = buffer->Begin ();
       i.Next (6);
@@ -146,12 +146,12 @@
     }
 }
 uint32_t
-UdpHeader::DeserializeFrom (Buffer::Iterator start)
+UdpHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
   m_sourcePort = i.ReadNtohU16 ();
   m_destinationPort = i.ReadNtohU16 ();
-  m_payloadSize = i.ReadNtohU16 () - GetSize ();
+  m_payloadSize = i.ReadNtohU16 () - GetSerializedSize ();
   if (m_calcChecksum) 
     {
       // XXX verify checksum.
--- a/src/internet-node/udp-header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/udp-header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -42,7 +42,7 @@
    * Creates a null header
    */
   UdpHeader ();
-  virtual ~UdpHeader ();
+  ~UdpHeader ();
 
   /**
    * \brief Enable checksum calculation for UDP (XXX currently has no effect)
@@ -84,13 +84,13 @@
                            Ipv4Address destination,
                            uint8_t protocol);
 
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
-
   uint16_t m_sourcePort;
   uint16_t m_destinationPort;
   uint16_t m_payloadSize;
@@ -99,6 +99,6 @@
   static bool m_calcChecksum;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* UDP_HEADER */
--- a/src/internet-node/wscript	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/internet-node/wscript	Thu Aug 09 13:42:42 2007 +0200
@@ -34,4 +34,5 @@
         'ascii-trace.h',
         'pcap-trace.h',
         'ipv4-header.h',
+        'udp-header.h',
         ]
--- a/src/node/ethernet-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/ethernet-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -27,14 +27,14 @@
 
 NS_DEBUG_COMPONENT_DEFINE ("EthernetHeader");
 
-NS_HEADER_ENSURE_REGISTERED (ns3::EthernetHeader);
+namespace ns3 {
 
-namespace ns3 {
+NS_HEADER_ENSURE_REGISTERED (EthernetHeader);
 
 uint32_t
 EthernetHeader::GetUid (void)
 {
-  static uint32_t uid = Header::Register<EthernetHeader> ("EthernetHeader.ns3");
+  static uint32_t uid = AllocateUid<EthernetHeader> ("EthernetHeader.ns3");
   return uid;
 }
 
@@ -48,9 +48,6 @@
     m_lengthType (0)
 {}
 
-EthernetHeader::~EthernetHeader ()
-{}
-
 void 
 EthernetHeader::SetLengthType (uint16_t lengthType)
 {
@@ -108,13 +105,13 @@
 }
 
 std::string
-EthernetHeader::DoGetName (void) const
+EthernetHeader::GetName (void) const
 {
   return "ETHERNET";
 }
 
 void 
-EthernetHeader::PrintTo (std::ostream &os) const
+EthernetHeader::Print (std::ostream &os) const
 {
   // ethernet, right ?
   if (m_enPreambleSfd)
@@ -139,7 +136,7 @@
 }
 
 void
-EthernetHeader::SerializeTo (Buffer::Iterator start) const
+EthernetHeader::Serialize (Buffer::Iterator start) const
 {
   Buffer::Iterator i = start;
   
@@ -152,7 +149,7 @@
   i.WriteU16 (m_lengthType);
 }
 uint32_t
-EthernetHeader::DeserializeFrom (Buffer::Iterator start)
+EthernetHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
 
--- a/src/node/ethernet-header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/ethernet-header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -62,7 +62,6 @@
    * By default, does not add or remove an ethernet preamble
    */
   EthernetHeader ();
-  virtual ~EthernetHeader ();
   /**
    * \param size The size of the payload in bytes
    */
@@ -104,17 +103,16 @@
    */
   uint32_t GetHeaderSize() const;
 
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 private:
   static const int PREAMBLE_SIZE = 8; /// size of the preamble_sfd header field
   static const int LENGTH_SIZE = 2;   /// size of the length_type header field
   static const int MAC_ADDR_SIZE = 6; /// size of src/dest addr header fields
 
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
-
   /**
    * If false, the preamble/sfd are not serialised/deserialised.
    */
--- a/src/node/ethernet-trailer.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/ethernet-trailer.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -26,16 +26,16 @@
 
 NS_DEBUG_COMPONENT_DEFINE ("EthernetTrailer");
 
-NS_TRAILER_ENSURE_REGISTERED (ns3::EthernetTrailer);
+namespace ns3 {
 
-namespace ns3 {
+NS_TRAILER_ENSURE_REGISTERED (EthernetTrailer);
 
 bool EthernetTrailer::m_calcFcs = false;
 
 uint32_t
 EthernetTrailer::GetUid (void)
 {
-  static uint32_t uid = Trailer::Register<EthernetTrailer> ("EthernetTrailer.ns3");
+  static uint32_t uid = AllocateUid<EthernetTrailer> ("EthernetTrailer.ns3");
   return uid;
 }
 
@@ -44,9 +44,6 @@
   Init();
 }
 
-EthernetTrailer::~EthernetTrailer ()
-{}
-
 void EthernetTrailer::Init()
 {
   m_fcs = 0;
@@ -94,13 +91,13 @@
   return GetSerializedSize();
 }
 std::string
-EthernetTrailer::DoGetName (void) const
+EthernetTrailer::GetName (void) const
 {
   return "ETHERNET";
 }
 
 void 
-EthernetTrailer::PrintTo (std::ostream &os) const
+EthernetTrailer::Print (std::ostream &os) const
 {
   os << " fcs=" << m_fcs;
 }
@@ -111,7 +108,7 @@
 }
 
 void
-EthernetTrailer::SerializeTo (Buffer::Iterator end) const
+EthernetTrailer::Serialize (Buffer::Iterator end) const
 {
   Buffer::Iterator i = end;
   i.Prev(GetSerializedSize());
@@ -119,7 +116,7 @@
   i.WriteU32 (m_fcs);
 }
 uint32_t
-EthernetTrailer::DeserializeFrom (Buffer::Iterator end)
+EthernetTrailer::Deserialize (Buffer::Iterator end)
 {
   Buffer::Iterator i = end;
   uint32_t size = GetSerializedSize();
--- a/src/node/ethernet-trailer.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/ethernet-trailer.h	Thu Aug 09 13:42:42 2007 +0200
@@ -43,7 +43,7 @@
    * \brief Construct a null ethernet trailer
    */
   EthernetTrailer ();
-  virtual ~EthernetTrailer ();
+
   /**
    * \brief Enable or disabled FCS checking and calculations
    * \param enable If true, enables FCS calculations.
@@ -81,12 +81,12 @@
    */ 
   uint32_t GetTrailerSize() const;
 
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator end) const;
+  uint32_t Deserialize (Buffer::Iterator end);
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator end) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator end);
 
   /**
    * Initializes the trailer parameters during construction.
@@ -102,7 +102,7 @@
 
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 
 #endif /* ETHERNET_TRAILER_H */
--- a/src/node/ipv4-address.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/ipv4-address.h	Thu Aug 09 13:42:42 2007 +0200
@@ -116,7 +116,7 @@
    * (bitwise and) with a network mask, yielding an IPv4 network
    * address.
    *
-   * \param a network mask 
+   * \param mask a network mask 
    */
   Ipv4Address CombineMask (Ipv4Mask const &mask) const;
 
--- a/src/node/llc-snap-header.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/llc-snap-header.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -23,23 +23,20 @@
 #include "ns3/assert.h"
 #include <string>
 
-NS_HEADER_ENSURE_REGISTERED (ns3::LlcSnapHeader);
+namespace ns3 {
 
-
-namespace ns3 {
+NS_HEADER_ENSURE_REGISTERED (LlcSnapHeader);
 
 uint32_t
 LlcSnapHeader::GetUid (void)
 {
-  static uint32_t uid = Header::Register<LlcSnapHeader> ("LlcSnapHeader.ns3");
+  static uint32_t uid = AllocateUid<LlcSnapHeader> ("LlcSnapHeader.ns3");
   return uid;
 }
 
 LlcSnapHeader::LlcSnapHeader ()
 {}
 
-LlcSnapHeader::~LlcSnapHeader ()
-{}
 void 
 LlcSnapHeader::SetType (uint16_t type)
 {
@@ -58,13 +55,13 @@
 }
 
 std::string
-LlcSnapHeader::DoGetName (void) const
+LlcSnapHeader::GetName (void) const
 {
   return "LLCSNAP";
 }
 
 void 
-LlcSnapHeader::PrintTo (std::ostream &os) const
+LlcSnapHeader::Print (std::ostream &os) const
 {
   os << "(type 0x";
   os.setf (std::ios::hex, std::ios::basefield);
@@ -74,7 +71,7 @@
 }
 
 void
-LlcSnapHeader::SerializeTo (Buffer::Iterator start) const
+LlcSnapHeader::Serialize (Buffer::Iterator start) const
 {
   Buffer::Iterator i = start;
   uint8_t buf[] = {0xaa, 0xaa, 0x03, 0, 0, 0};
@@ -82,7 +79,7 @@
   i.WriteHtonU16 (m_etherType);
 }
 uint32_t
-LlcSnapHeader::DeserializeFrom (Buffer::Iterator start)
+LlcSnapHeader::Deserialize (Buffer::Iterator start)
 {
   Buffer::Iterator i = start;
   i.Next (5+1);
@@ -91,4 +88,4 @@
 }
 
 
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/llc-snap-header.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/llc-snap-header.h	Thu Aug 09 13:42:42 2007 +0200
@@ -34,21 +34,19 @@
   static uint32_t GetUid (void);
 
   LlcSnapHeader ();
-  virtual ~LlcSnapHeader ();
-
 
   void SetType (uint16_t type);
   uint16_t GetType (void);
 
+  std::string GetName (void) const;
+  void Print (std::ostream &os) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
 private:
-  virtual std::string DoGetName (void) const;
-  virtual void PrintTo (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void SerializeTo (Buffer::Iterator start) const;
-  virtual uint32_t DeserializeFrom (Buffer::Iterator start);
   uint16_t m_etherType;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* LLC_SNAP_HEADER_H */
--- a/src/node/node-list.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/node-list.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -40,6 +40,30 @@
 
 namespace ns3 {
 
+NodeListIndex::NodeListIndex ()
+  : m_index (0)
+{}
+NodeListIndex::NodeListIndex (uint32_t index)
+  : m_index (index)
+{}
+void 
+NodeListIndex::Print (std::ostream &os)
+{
+  os << "nodeid=" << m_index;
+}
+uint16_t 
+NodeListIndex::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<NodeListIndex> ("NodeListIndex");
+  return uid;
+}
+uint32_t 
+NodeListIndex::Get (void) const
+{
+  return m_index;
+}
+
+
 /**
  * The private node list used by the static-based API
  */
@@ -109,8 +133,8 @@
 TraceResolver *
 NodeListPriv::CreateTraceResolver (TraceContext const &context)
 {
-  ArrayTraceResolver<Ptr<Node> > *resolver =
-    new ArrayTraceResolver<Ptr<Node> >
+  ArrayTraceResolver<Ptr<Node>, NodeListIndex> *resolver =
+    new ArrayTraceResolver<Ptr<Node>, NodeListIndex>
     (context, 
      MakeCallback (&NodeListPriv::GetNNodes, this),
      MakeCallback (&NodeListPriv::GetNode, this));
--- a/src/node/node-list.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/node-list.h	Thu Aug 09 13:42:42 2007 +0200
@@ -23,7 +23,7 @@
 #define NODE_LIST_H
 
 #include <vector>
-#include "ns3/array-trace-resolver.h"
+#include "ns3/trace-context-element.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
@@ -32,6 +32,19 @@
 class TraceResolver;
 class TraceContext;
 
+class NodeListIndex : public TraceContextElement
+{
+public:
+  NodeListIndex ();
+  NodeListIndex (uint32_t index);
+  void Print (std::ostream &os);
+  static uint16_t GetUid (void);
+  uint32_t Get (void) const;
+private:
+  uint32_t m_index;
+};
+
+
 /**
  * \brief the list of simulation nodes.
  *
@@ -40,7 +53,6 @@
 class NodeList
 {
 public:
-  typedef ArrayTraceResolver<Ptr<Node> >::Index NodeIndex;
   typedef std::vector< Ptr<Node> >::iterator Iterator;
 
   /**
--- a/src/node/node.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/node.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -25,11 +25,37 @@
 #include "packet-socket-factory.h"
 #include "ns3/simulator.h"
 #include "ns3/composite-trace-resolver.h"
+#include "ns3/array-trace-resolver.h"
 
 namespace ns3{
 
 const InterfaceId Node::iid = MakeInterfaceId ("Node", Object::iid);
 
+NodeNetDeviceIndex::NodeNetDeviceIndex ()
+  : m_index (0)
+{}
+NodeNetDeviceIndex::NodeNetDeviceIndex (uint32_t index)
+  : m_index (index)
+{}
+uint32_t 
+NodeNetDeviceIndex::Get (void) const
+{
+  return m_index;
+}
+void 
+NodeNetDeviceIndex::Print (std::ostream &os) const
+{
+  os << "device=" << m_index;
+}
+uint16_t 
+NodeNetDeviceIndex::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<NodeNetDeviceIndex> ("NodeNetDeviceIndex");
+  return uid;
+}
+
+
+
 Node::Node()
   : m_id(0), 
     m_sid(0)
@@ -118,10 +144,11 @@
 TraceResolver *
 Node::CreateDevicesTraceResolver (const TraceContext &context)
 {
-  ArrayTraceResolver<Ptr<NetDevice> > *resolver = 
-    new ArrayTraceResolver<Ptr<NetDevice> > (context,
-                                             MakeCallback (&Node::GetNDevices, this), 
-                                             MakeCallback (&Node::GetDevice, this));
+  ArrayTraceResolver<Ptr<NetDevice>,NodeNetDeviceIndex> *resolver = 
+    new ArrayTraceResolver<Ptr<NetDevice>,NodeNetDeviceIndex> 
+    (context,
+     MakeCallback (&Node::GetNDevices, this), 
+     MakeCallback (&Node::GetDevice, this));
   
   return resolver;
 }
@@ -130,8 +157,7 @@
 Node::DoFillTraceResolver (CompositeTraceResolver &resolver)
 {
   resolver.Add ("devices", 
-                MakeCallback (&Node::CreateDevicesTraceResolver, this),
-                Node::DEVICES);
+                MakeCallback (&Node::CreateDevicesTraceResolver, this));
 }
 
 void 
--- a/src/node/node.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/node.h	Thu Aug 09 13:42:42 2007 +0200
@@ -25,7 +25,7 @@
 
 #include "ns3/object.h"
 #include "ns3/callback.h"
-#include "ns3/array-trace-resolver.h"
+#include "ns3/trace-context-element.h"
 
 namespace ns3 {
 
@@ -37,6 +37,18 @@
 class Address;
 class CompositeTraceResolver;
 
+class NodeNetDeviceIndex : public TraceContextElement
+{
+public:
+  NodeNetDeviceIndex ();
+  NodeNetDeviceIndex (uint32_t index);
+  uint32_t Get (void) const;
+  void Print (std::ostream &os) const;
+  static uint16_t GetUid (void);
+private:
+  uint32_t m_index;
+};
+
 /**
  * \brief A network Node.
  *
@@ -58,7 +70,6 @@
 {
 public:
   static const InterfaceId iid;
-  typedef ArrayTraceResolver<Ptr<NetDevice> >::Index NetDeviceIndex;
 
   /**
    * Must be invoked by subclasses only.
@@ -204,9 +215,6 @@
   void Construct (void);
   TraceResolver *CreateDevicesTraceResolver (const TraceContext &context);
 
-  enum TraceSource {
-    DEVICES
-  };
   struct ProtocolHandlerEntry {
     ProtocolHandler handler;
     uint16_t protocol;
--- a/src/node/queue.cc	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/queue.cc	Thu Aug 09 13:42:42 2007 +0200
@@ -31,6 +31,52 @@
 static ClassIdDefaultValue g_classIdDefaultValue ("Queue", "Packet Queue",
                                                   Queue::iid, "DropTailQueue");
 
+
+uint16_t 
+QueueTraceType::GetUid (void)
+{
+  static uint16_t uid = AllocateUid<QueueTraceType> ("QueueTraceType");
+  return uid;
+}
+QueueTraceType::QueueTraceType ()
+  : m_type (QueueTraceType::ENQUEUE)
+{}
+QueueTraceType::QueueTraceType (enum Type type)
+  : m_type (type)
+{}
+bool 
+QueueTraceType::IsEnqueue (void) const
+{
+  return m_type == ENQUEUE;
+}
+bool 
+QueueTraceType::IsDequeue (void) const
+{
+  return m_type == DEQUEUE;
+}
+bool 
+QueueTraceType::IsDrop (void) const
+{
+  return m_type == DROP;
+}
+
+void 
+QueueTraceType::Print (std::ostream &os) const
+{
+  os << "queue-";
+  switch (m_type) {
+  case QueueTraceType::ENQUEUE:
+    os << "enqueue";
+    break;
+  case QueueTraceType::DEQUEUE:
+    os << "dequeue";
+    break;
+  case QueueTraceType::DROP:
+    os << "drop";
+    break;
+  }
+}
+
 Queue::Queue() : 
   m_nBytes(0), 
   m_nTotalReceivedBytes(0),
@@ -52,9 +98,9 @@
 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);
+  resolver->Add ("enqueue", m_traceEnqueue, QueueTraceType (QueueTraceType::ENQUEUE));
+  resolver->Add ("dequeue", m_traceDequeue, QueueTraceType (QueueTraceType::DEQUEUE));
+  resolver->Add ("drop", m_traceDrop, QueueTraceType (QueueTraceType::DROP));
   return resolver;
 }
 
--- a/src/node/queue.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/node/queue.h	Thu Aug 09 13:42:42 2007 +0200
@@ -31,11 +31,32 @@
 #include "ns3/object.h"
 #include "ns3/callback-trace-source.h"
 #include "ns3/trace-resolver.h"
+#include "ns3/trace-context-element.h"
 
 namespace ns3 {
 
 class StringEnumDefaultValue;
 
+class QueueTraceType : public TraceContextElement
+{
+public:
+  enum Type {
+    ENQUEUE,
+    DEQUEUE,
+    DROP
+  };
+  static uint16_t GetUid (void);
+  QueueTraceType ();
+  QueueTraceType (enum Type type);
+  bool IsEnqueue (void) const;
+  bool IsDequeue (void) const;
+  bool IsDrop (void) const;
+  void Print (std::ostream &os) const;
+private:
+  enum Type m_type;
+};
+
+
 /**
  * \brief Abstract base class for packet Queues
  * 
@@ -46,11 +67,6 @@
 public:
   static const InterfaceId iid;
 
-  enum TraceType {
-    ENQUEUE,
-    DEQUEUE,
-    DROP,
-  };
   Queue ();
   virtual ~Queue ();
 
--- a/src/simulator/scheduler.h	Thu Aug 09 13:38:04 2007 +0200
+++ b/src/simulator/scheduler.h	Thu Aug 09 13:42:42 2007 +0200
@@ -58,9 +58,7 @@
   virtual ~Scheduler () = 0;
 
   /**
-   * \param event event to store in the event list
-   * \param key timecode associated to this new event
-   * \returns an event id which identifies the event inserted
+   * \param id event to store in the event list
    *
    * This method takes ownership of the event pointer.
    */
@@ -83,9 +81,8 @@
   virtual EventId RemoveNext (void) = 0;
   /**
    * \param id the id of the event to remove
-   * \param key the timecode of the event removed
-   * \returns a pointer to the event removed. The caller
-   *      takes ownership of the returned pointer.
+   * \returns true if the id was found and removed 
+   *          successfully, false otherwise.
    *
    * This methods cannot be invoked if the list is empty.
    */