force users to register their header/trailer uid strings by hand rather than do lazy uid allocation.
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Aug 2007 16:37:16 +0200
changeset 1151 527d7b7e25af
parent 1150 fcdda7ef3cee
child 1152 1d06449f0a98
force users to register their header/trailer uid strings by hand rather than do lazy uid allocation.
samples/main-header.cc
src/common/chunk-registry.cc
src/common/chunk-registry.h
src/common/chunk.cc
src/common/chunk.h
src/common/header.cc
src/common/header.h
src/common/packet-metadata-test.cc
src/common/packet-metadata.h
src/common/packet-printer.h
src/common/trailer.h
src/common/wscript
src/internet-node/arp-header.cc
src/internet-node/arp-header.h
src/internet-node/ipv4-header.cc
src/internet-node/ipv4-header.h
src/internet-node/udp-header.cc
src/internet-node/udp-header.h
src/node/ethernet-header.cc
src/node/ethernet-header.h
src/node/ethernet-trailer.cc
src/node/ethernet-trailer.h
src/node/llc-snap-header.cc
src/node/llc-snap-header.h
--- a/samples/main-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/samples/main-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -10,7 +10,7 @@
 class MyHeader : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   MyHeader ();
   virtual ~MyHeader ();
@@ -35,14 +35,15 @@
 MyHeader::~MyHeader ()
 {}
 
-std::string
+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.
-  return "MyHeader.test.nsnam.org";
+  static uint32_t uid = Header::Register<MyHeader> ("MyHeader.test.nsnam.org");
+  return uid;
 }
 
 std::string 
--- a/src/common/chunk-registry.cc	Sat Aug 04 16:07:46 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include "chunk-registry.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
--- a/src/common/chunk-registry.h	Sat Aug 04 16:07:46 2007 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef CHUNK_REGISTRY_H
-#define CHUNK_REGISTRY_H
-
-#include "buffer.h"
-#include "ns3/ptr.h"
-#include "ns3/callback.h"
-#include <string>
-
-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 GetHeaderUid (void);
-  template <typename T>
-  static uint32_t GetTrailerUid (void);
-
-  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);
-
-};
-
-} // namespace ns3
-
-namespace ns3 {
-
-template <typename T>
-uint32_t 
-ChunkRegistry::GetHeaderUid (void)
-{
-  return GetUid<T> (true);
-}
-template <typename T>
-uint32_t 
-ChunkRegistry::GetTrailerUid (void)
-{
-  return GetUid<T> (false);
-}
-
-template <typename T>
-uint32_t 
-ChunkRegistry::GetUid (bool isHeader)
-{
-  InfoVector *vec = GetInfoVector ();
-  uint32_t uid = 1; 
-  for (InfoVector::iterator i = vec->begin (); i != vec->end (); i++)
-    {
-      if (i->uidString == T::GetUid ())
-	{
-	  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 = T::GetUid ();
-  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_REGISTRY_H */
--- a/src/common/chunk.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/chunk.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -62,4 +62,100 @@
   return os;
 }
 
-}; // namespace ns3
+
+/**************************************
+ * 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	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/chunk.h	Sat Aug 04 16:37:16 2007 +0200
@@ -25,6 +25,8 @@
 #include <stdint.h>
 #include <ostream>
 #include "buffer.h"
+#include "ns3/ptr.h"
+#include "ns3/callback.h"
 
 namespace ns3 {
 
@@ -48,6 +50,151 @@
 
 std::ostream& operator<< (std::ostream& os, Chunk const& chunk);
 
-}; // 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/header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -26,4 +26,4 @@
 Header::~Header ()
 {}
 
-}; // namespace ns3
+} // namespace ns3
--- a/src/common/header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -63,6 +63,9 @@
 class Header : public Chunk {
 public:
   virtual ~Header ();
+protected:
+  template <typename T>
+  static uint32_t Register (std::string uuid);
 private:
   /**
    * \returns a user-readable name to identify this type of header.
@@ -115,6 +118,18 @@
   virtual uint32_t DeserializeFrom (Buffer::Iterator start) = 0;
 };
 
-}; // namespace ns3
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+uint32_t 
+Header::Register (std::string uuid)
+{
+  return ChunkRegistry::RegisterHeader<T> (uuid);
+}
+
+
+} // namespace ns3
 
 #endif /* HEADER_H */
--- a/src/common/packet-metadata-test.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/packet-metadata-test.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -35,7 +35,7 @@
 class HistoryHeader : public Header
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
   HistoryHeader ();
   bool IsOk (void) const;
 private:
@@ -48,12 +48,13 @@
 };
 
 template <int N>
-std::string
+uint32_t
 HistoryHeader<N>::GetUid (void)
 {
   std::ostringstream oss;
   oss << N << "HistoryHeader.ns3";
-  return oss.str ();
+  static uint32_t uid = Header::Register<HistoryHeader<N> > (oss.str());
+  return uid;
 }
 
 template <int N>
@@ -114,7 +115,7 @@
 class HistoryTrailer : public Trailer
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
   HistoryTrailer ();
   bool IsOk (void) const;
 private:
@@ -127,12 +128,13 @@
 };
 
 template <int N>
-std::string
+uint32_t
 HistoryTrailer<N>::GetUid (void)
 {
   std::ostringstream oss;
   oss << N << "HistoryTrailer.ns3";
-  return oss.str ();
+  static uint32_t uid = Trailer::Register<HistoryTrailer<N> > (oss.str ());
+  return uid;
 }
 
 
--- a/src/common/packet-metadata.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/packet-metadata.h	Sat Aug 04 16:37:16 2007 +0200
@@ -257,26 +257,26 @@
 void 
 PacketMetadata::AddHeader (T const &header, uint32_t size)
 {
-  DoAddHeader (ChunkRegistry::GetHeaderUid<T> () << 1, size);
+  DoAddHeader (T::GetUid () << 1, size);
 }
 
 template <typename T>
 void 
 PacketMetadata::RemoveHeader (T const &header, uint32_t size)
 {
-  DoRemoveHeader (ChunkRegistry::GetHeaderUid<T> () << 1, size);
+  DoRemoveHeader (T::GetUid () << 1, size);
 }
 template <typename T>
 void 
 PacketMetadata::AddTrailer (T const &trailer, uint32_t size)
 {
-  DoAddTrailer (ChunkRegistry::GetTrailerUid<T> () << 1, size);
+  DoAddTrailer (T::GetUid () << 1, size);
 }
 template <typename T>
 void 
 PacketMetadata::RemoveTrailer (T const &trailer, uint32_t size)
 {
-  DoRemoveTrailer (ChunkRegistry::GetTrailerUid<T> () << 1, size);
+  DoRemoveTrailer (T::GetUid () << 1, size);
 }
 
 
--- a/src/common/packet-printer.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/packet-printer.h	Sat Aug 04 16:37:16 2007 +0200
@@ -24,7 +24,7 @@
 #include "ns3/callback.h"
 #include "ns3/ptr.h"
 #include "buffer.h"
-#include "chunk-registry.h"
+#include "chunk.h"
 #include <vector>
 
 namespace ns3 {
@@ -158,7 +158,7 @@
                                  ChunkFragmentPrinter fragmentPrinter)
 {
   Printer p;
-  p.m_chunkUid = ChunkRegistry::GetHeaderUid<T> ();
+  p.m_chunkUid = T::GetUid ();
   p.m_printer = printer.GetImpl ();
   p.m_fragmentPrinter = fragmentPrinter;
   m_printerList.push_back (p);
@@ -170,7 +170,7 @@
                                  ChunkFragmentPrinter fragmentPrinter)
 {
   Printer p;
-  p.m_chunkUid = ChunkRegistry::GetTrailerUid<T> ();
+  p.m_chunkUid = T::GetUid ();
   p.m_printer = printer.GetImpl ();
   p.m_fragmentPrinter = fragmentPrinter;
   m_printerList.push_back (p);
--- a/src/common/trailer.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/trailer.h	Sat Aug 04 16:37:16 2007 +0200
@@ -86,6 +86,9 @@
 class Trailer : public Chunk {
 public:
   virtual ~Trailer ();
+protected:
+  template <typename T>
+  static uint32_t Register (std::string uidString);
 private:
   /**
    * \returns a user-readable name to identify this type of header.
@@ -142,6 +145,18 @@
   virtual uint32_t DeserializeFrom (Buffer::Iterator end) = 0;
 };
 
-}; // namespace ns3
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+uint32_t 
+Trailer::Register (std::string uidString)
+{
+  return ChunkRegistry::RegisterTrailer<T> (uidString);
+}
+
+
+} // namespace ns3
 
 #endif /* TRAILER_H */
--- a/src/common/wscript	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/common/wscript	Sat Aug 04 16:37:16 2007 +0200
@@ -10,7 +10,6 @@
         'chunk.cc',
         'header.cc',
         'trailer.cc',
-        'chunk-registry.cc',
         'packet-printer.cc',
         'packet-metadata.cc',
         'packet-metadata-test.cc',
@@ -36,7 +35,6 @@
         'tags.h',
         'packet.h',
         'packet-printer.h',
-        'chunk-registry.h',
         'packet-metadata.h',
         'uv-trace-source.h',
         'sv-trace-source.h',
--- a/src/internet-node/arp-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/arp-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -25,10 +25,11 @@
 
 namespace ns3 {
 
-std::string
+uint32_t
 ArpHeader::GetUid (void)
 {
-  return "ArpHeader.ns3";
+  static uint32_t uid = Header::Register<ArpHeader> ("ArpHeader.ns3");
+  return uid;
 }
 
 ArpHeader::~ArpHeader ()
--- a/src/internet-node/arp-header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/arp-header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -34,7 +34,7 @@
 class ArpHeader : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   virtual ~ArpHeader ();
 
--- a/src/internet-node/ipv4-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/ipv4-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -30,10 +30,11 @@
 
 bool Ipv4Header::m_calcChecksum = false;
 
-std::string
+uint32_t
 Ipv4Header::GetUid (void)
 {
-  return "Ipv4Header.ns3";
+  static uint32_t uid = Header::Register<Ipv4Header> ("Ipv4Header.ns3");
+  return uid;
 }
 
 Ipv4Header::Ipv4Header ()
--- a/src/internet-node/ipv4-header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/ipv4-header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -32,7 +32,7 @@
 class Ipv4Header : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
   /**
    * \brief Construct a null IPv4 header
    */
--- a/src/internet-node/udp-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/udp-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -26,10 +26,11 @@
 
 bool UdpHeader::m_calcChecksum = false;
 
-std::string
+uint32_t
 UdpHeader::GetUid (void)
 {
-  return "UdpHeader.ns3";
+  static uint32_t uid = Header::Register<UdpHeader> ("UdpHeader.ns3");
+  return uid;
 }
 
 /* The magic values below are used only for debugging.
--- a/src/internet-node/udp-header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/internet-node/udp-header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -34,7 +34,7 @@
 class UdpHeader : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   /**
    * \brief Constructor
--- a/src/node/ethernet-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/ethernet-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -29,10 +29,11 @@
 
 namespace ns3 {
 
-std::string
+uint32_t
 EthernetHeader::GetUid (void)
 {
-  return "EthernetHeader.ns3";
+  static uint32_t uid = Header::Register<EthernetHeader> ("EthernetHeader.ns3");
+  return uid;
 }
 
 EthernetHeader::EthernetHeader (bool hasPreamble)
--- a/src/node/ethernet-header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/ethernet-header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -49,7 +49,7 @@
 class EthernetHeader : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   /**
    * \brief Construct a null ethernet header
--- a/src/node/ethernet-trailer.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/ethernet-trailer.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -30,10 +30,11 @@
 
 bool EthernetTrailer::m_calcFcs = false;
 
-std::string
+uint32_t
 EthernetTrailer::GetUid (void)
 {
-  return "EthernetTrailer.ns3";
+  static uint32_t uid = Trailer::Register<EthernetTrailer> ("EthernetTrailer.ns3");
+  return uid;
 }
 
 EthernetTrailer::EthernetTrailer ()
--- a/src/node/ethernet-trailer.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/ethernet-trailer.h	Sat Aug 04 16:37:16 2007 +0200
@@ -37,7 +37,7 @@
 class EthernetTrailer : public Trailer 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   /**
    * \brief Construct a null ethernet trailer
--- a/src/node/llc-snap-header.cc	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/llc-snap-header.cc	Sat Aug 04 16:37:16 2007 +0200
@@ -26,10 +26,11 @@
 
 namespace ns3 {
 
-std::string
+uint32_t
 LlcSnapHeader::GetUid (void)
 {
-  return "LlcSnapHeader.ns3";
+  static uint32_t uid = Header::Register<LlcSnapHeader> ("LlcSnapHeader.ns3");
+  return uid;
 }
 
 LlcSnapHeader::LlcSnapHeader ()
--- a/src/node/llc-snap-header.h	Sat Aug 04 16:07:46 2007 +0200
+++ b/src/node/llc-snap-header.h	Sat Aug 04 16:37:16 2007 +0200
@@ -31,7 +31,7 @@
 class LlcSnapHeader : public Header 
 {
 public:
-  static std::string GetUid (void);
+  static uint32_t GetUid (void);
 
   LlcSnapHeader ();
   virtual ~LlcSnapHeader ();