merge with ns-3-dev
authorGustavo J. A. M. Carneiro <gjc@inescporto.pt>
Wed, 05 Sep 2007 18:35:39 +0100
changeset 1737 e72c130c3a59
parent 1728 190372a33951 (current diff)
parent 1312 8bc3f26344b9 (diff)
child 1738 6a3e37af9d24
merge with ns-3-dev
examples/csma-cd-one-subnet.cc
samples/main-packet.cc
src/common/chunk.cc
src/common/chunk.h
src/common/header.cc
src/common/trailer.cc
src/core/assert.cc
src/devices/csma-cd/backoff.cc
src/devices/csma-cd/backoff.h
src/devices/csma-cd/csma-cd-channel.cc
src/devices/csma-cd/csma-cd-channel.h
src/devices/csma-cd/csma-cd-ipv4-topology.cc
src/devices/csma-cd/csma-cd-ipv4-topology.h
src/devices/csma-cd/csma-cd-net-device.cc
src/devices/csma-cd/csma-cd-net-device.h
src/devices/csma-cd/csma-cd-topology.cc
src/devices/csma-cd/csma-cd-topology.h
src/devices/csma-cd/wscript
src/internet-node/arp-private.cc
src/internet-node/arp-private.h
src/internet-node/ipv4-l3-protocol.cc
src/internet-node/ipv4-private.cc
src/internet-node/ipv4-private.h
src/internet-node/l3-demux.cc
src/internet-node/l3-demux.h
src/internet-node/l3-protocol.cc
src/internet-node/l3-protocol.h
src/internet-node/wscript
src/node/ipv4-address.cc
src/node/ipv4-address.h
src/node/mac-address.cc
src/node/mac-address.h
src/simulator/wscript
utils/wscript
wscript
--- a/.hgtags	Mon Jul 30 14:48:56 2007 +0100
+++ b/.hgtags	Wed Sep 05 18:35:39 2007 +0100
@@ -3,3 +3,4 @@
 0dc81e76166c56aaae64da48b673b62155943aad packet-history-working
 38099dd26e9467b8f49f8632f22789858149a6e7 release ns-3.0.3
 5701e60bf01a8ac1308945e69001e0cc07948faf release ns-3.0.4
+08046b6aef37932507696a2f2f427b42d693781e release ns-3.0.5
--- a/AUTHORS	Mon Jul 30 14:48:56 2007 +0100
+++ b/AUTHORS	Wed Sep 05 18:35:39 2007 +0100
@@ -3,4 +3,5 @@
 Craig Dowell (craigdo@ee.washington.edu)
 Tom Henderson (tomhend@u.washington.edu)
 Mathieu Lacage (mathieu.lacage@sophia.inria.fr)
+Emmanuelle Laprise (emmmanuelle.laprise@bluekazoo.ca)
 George F. Riley (riley@ece.gatech.edu)
--- a/RELEASE_NOTES	Mon Jul 30 14:48:56 2007 +0100
+++ b/RELEASE_NOTES	Wed Sep 05 18:35:39 2007 +0100
@@ -3,12 +3,16 @@
 
 This file contains ns-3 release notes (most recent releases first).
 
-Release 3.0.5 (2007/08/XX)
+Release 3.0.5 (2007/08/15)
 ========================
 
-  - Add CSMA/CD model (Emmanuelle Laprise)
-  - Modularize ipv4 routing support (Gustavo Carneiro)
-  - Add mobility framework and basic mobility models
+  - Refactoring to support win32-based unix environments (Cygwin, mingw)
+  - "Packet socket" for allowing applications to access NetDevices directly
+  - Generalized, polymorphic Address class
+  - Add CSMA NetDevice model (from Emmanuelle Laprise)
+  - Modularize IPv4 routing support (from Gustavo Carneiro)
+  - Add mobility framework and basic mobility models 
+  - Global unicast centralized routing 
 
 Release 3.0.4 (2007/07/15)
 ========================
--- a/VERSION	Mon Jul 30 14:48:56 2007 +0100
+++ b/VERSION	Wed Sep 05 18:35:39 2007 +0100
@@ -1,1 +1,1 @@
-3.0.4
+3.0.5
--- a/doc/doxygen.conf	Mon Jul 30 14:48:56 2007 +0100
+++ b/doc/doxygen.conf	Wed Sep 05 18:35:39 2007 +0100
@@ -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/doc/release_steps.txt	Mon Jul 30 14:48:56 2007 +0100
+++ b/doc/release_steps.txt	Wed Sep 05 18:35:39 2007 +0100
@@ -5,23 +5,20 @@
    - revise and check in RELEASE_NOTES
    - update and check in VERSION to the latest release number
 2. make a new "architecture.pdf" document and place it in the doc/ directory
-3. add current version of waf script from subversion:
-   - svn checkout http://waf.googlecode.com/svn/tags/ns3/ waf
-   - build waf script and put it into top of ns-3-dev
-4. cd ns-3-dev; ./waf configure; ./waf dist
-5. test tarball on release platforms (run-tests and simple-p2p)
-6. tag ns-3-dev with "release ns-3.0.X"
+3. cd ns-3-dev; ./waf configure; ./waf dist
+4. test tarball on release platforms (waf check and maybe some other scripts)
+5. tag ns-3-dev with "release ns-3.0.X"
   - hg tag "release ns-3.0.x"
   - hg push 
-7. clone the tagged ns-3-dev and place it on the repository
+6. clone the tagged ns-3-dev and place it on the repository
   - ssh code.nsnam.org; sudo; su code;
   - cp -r /home/code/repos/ns-3-dev /home/code/repos/ns-3.0.x
   - cd /home/code/repos/ns-3.0.x/.hg and edit the hgrc appropriately
-8. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
-9. update web page
+7. upload "ns-3.0.x.tar.bz2" to the releases/ directory on the server
+8. update web page
    - add link to news.html
    - update download.html
    - update roadmap.html
    - build and update Doxygen directory on the server
    - update and upload software architecture document (PDF, HTML)
-10. announce to ns-developers, with summary of release notes
+9. announce to ns-developers, with summary of release notes
--- a/examples/csma-cd-one-subnet.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * 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
- */
-
-// Port of ns-2/tcl/ex/simple.tcl to ns-3
-//
-// Network topology
-//
-//       n0    n1   n2   n3
-//       |     |    |    |
-//     =====================
-//
-// - CBR/UDP flows from n0 to n1, and from n3 to n0
-// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
-//   (i.e., DataRate of 448,000 bps)
-// - DropTail queues 
-// - Tracing of queues and packet receptions to file "csma-cd-one-subnet.tr"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <cassert>
-
-#include "ns3/command-line.h"
-#include "ns3/default-value.h"
-#include "ns3/ptr.h"
-#include "ns3/random-variable.h"
-#include "ns3/debug.h"
-
-#include "ns3/simulator.h"
-#include "ns3/nstime.h"
-#include "ns3/data-rate.h"
-
-#include "ns3/ascii-trace.h"
-#include "ns3/pcap-trace.h"
-#include "ns3/internet-node.h"
-#include "ns3/csma-cd-channel.h"
-#include "ns3/csma-cd-net-device.h"
-#include "ns3/csma-cd-topology.h"
-#include "ns3/csma-cd-ipv4-topology.h"
-#include "ns3/mac-address.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4.h"
-#include "ns3/socket.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/onoff-application.h"
-
-#include "ns3/ascii-trace.h"
-
-#include "ns3/trace-context.h"
-#include "ns3/trace-root.h"
-
-
-using namespace ns3;
-
-
-int main (int argc, char *argv[])
-{
-
-  // Users may find it convenient to turn on explicit debugging
-  // for selected modules; the below lines suggest how to do this
-#if 0 
-  DebugComponentEnable("CsmaCdNetDevice");
-  DebugComponentEnable("Ipv4L3Protocol");
-  DebugComponentEnable("NetDevice");
-  DebugComponentEnable("Channel");
-  DebugComponentEnable("CsmaCdChannel");
-  DebugComponentEnable("PacketSocket");
-#endif
-
-  // Set up some default values for the simulation.  Use the Bind()
-  // technique to tell the system what subclass of Queue to use,
-  // and what the queue limit is
-
-  // The below Bind command tells the queue factory which class to
-  // instantiate, when the queue factory is invoked in the topology code
-  Bind ("Queue", "DropTailQueue");
-
-  // Allow the user to override any of the defaults and the above
-  // Bind()s at run-time, via command-line arguments
-  CommandLine::Parse (argc, argv);
-
-  // Here, we will explicitly create four nodes.  In more sophisticated
-  // topologies, we could configure a node factory.
-  Ptr<Node> n0 = Create<InternetNode> ();
-  Ptr<Node> n1 = Create<InternetNode> (); 
-  Ptr<Node> n2 = Create<InternetNode> (); 
-  Ptr<Node> n3 = Create<InternetNode> ();
-
-  // We create the channels first without any IP addressing information
-  Ptr<CsmaCdChannel> channel0 = 
-    CsmaCdTopology::CreateCsmaCdChannel(
-      DataRate(5000000), MilliSeconds(2));
-
-  uint32_t n0ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n0, channel0, 
-                                         MacAddress("10:54:23:54:23:50"));
-  uint32_t n1ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n1, channel0,
-                                         MacAddress("10:54:23:54:23:51"));
-  uint32_t n2ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n2, channel0,
-                                         MacAddress("10:54:23:54:23:52"));
-  uint32_t n3ifIndex = CsmaCdIpv4Topology::AddIpv4CsmaCdNode (n3, channel0,
-                                         MacAddress("10:54:23:54:23:53"));
-
-  // Later, we add IP addresses.  
-  CsmaCdIpv4Topology::AddIpv4Address (
-      n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0"));
-
-  CsmaCdIpv4Topology::AddIpv4Address (
-      n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0"));
-
-  CsmaCdIpv4Topology::AddIpv4Address (
-      n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0"));
-  
-  CsmaCdIpv4Topology::AddIpv4Address (
-      n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0"));
-
-  // Create the OnOff application to send UDP datagrams of size
-  // 210 bytes at a rate of 448 Kb/s
-  // from n0 to n1
-  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
-    n0, 
-    Ipv4Address("10.1.1.2"), 
-    80, 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
-  // Start the application
-  ooff->Start(Seconds(1.0));
-  ooff->Stop (Seconds(10.0));
-
-  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
-  ooff = Create<OnOffApplication> (
-    n3, 
-    Ipv4Address("10.1.1.1"), 
-    80, 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
-  // Start the application
-  ooff->Start(Seconds(1.1));
-  ooff->Stop (Seconds(10.0));
- 
-  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
-  // Trace output will be sent to the csma-cd-one-subnet.tr file
-  AsciiTrace asciitrace ("csma-cd-one-subnet.tr");
-  asciitrace.TraceAllNetDeviceRx ();
-  asciitrace.TraceAllQueues ();
-
-  // Also configure some tcpdump traces; each interface will be traced
-  // The output files will be named 
-  // simple-point-to-point.pcap-<nodeId>-<interfaceId>
-  // and can be read by the "tcpdump -r" command (use "-tt" option to
-  // display timestamps correctly)
-  PcapTrace pcaptrace ("csma-cd-one-subnet.pcap");
-  pcaptrace.TraceAllIp ();
-
-  Simulator::Run ();
-    
-  Simulator::Destroy ();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-one-subnet.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,166 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - CBR/UDP flows from n0 to n1, and from n3 to n0
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "csma-one-subnet.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/debug.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/csma-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/csma-topology.h"
+#include "ns3/csma-ipv4-topology.h"
+#include "ns3/eui48-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/onoff-application.h"
+
+
+using namespace ns3;
+
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  DebugComponentEnable("CsmaNetDevice");
+  DebugComponentEnable("Ipv4L3Protocol");
+  DebugComponentEnable("NetDevice");
+  DebugComponentEnable("Channel");
+  DebugComponentEnable("CsmaChannel");
+  DebugComponentEnable("PacketSocket");
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  // Allow the user to override any of the defaults and the above
+  // Bind()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<CsmaChannel> channel0 = 
+    CsmaTopology::CreateCsmaChannel(
+      DataRate(5000000), MilliSeconds(2));
+
+  uint32_t n0ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n0, channel0, 
+                                         Eui48Address("10:54:23:54:23:50"));
+  uint32_t n1ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n1, channel0,
+                                         Eui48Address("10:54:23:54:23:51"));
+  uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channel0,
+                                         Eui48Address("10:54:23:54:23:52"));
+  uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channel0,
+                                         Eui48Address("10:54:23:54:23:53"));
+
+  // Later, we add IP addresses.  
+  CsmaIpv4Topology::AddIpv4Address (
+      n0, n0ifIndex, Ipv4Address("10.1.1.1"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n1, n1ifIndex, Ipv4Address("10.1.1.2"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n2, n2ifIndex, Ipv4Address("10.1.1.3"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n3, n3ifIndex, Ipv4Address("10.1.1.4"), Ipv4Mask("255.255.255.0"));
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  // from n0 to n1
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress ("10.1.1.2", 80), 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    InetSocketAddress ("10.1.1.1", 80), 
+    "Udp",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+ 
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the csma-one-subnet.tr file
+  AsciiTrace asciitrace ("csma-one-subnet.tr");
+  asciitrace.TraceAllNetDeviceRx ();
+  asciitrace.TraceAllQueues ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named 
+  // simple-point-to-point.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("csma-one-subnet.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/csma-packet-socket.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//       n0    n1   n2   n3
+//       |     |    |    |
+//     =====================
+//
+// - CBR/UDP flows from n0 to n1, and from n3 to n0
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "csma-one-subnet.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+#include "ns3/debug.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/csma-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/eui48-address.h"
+#include "ns3/packet-socket-address.h"
+#include "ns3/socket.h"
+#include "ns3/onoff-application.h"
+#include "ns3/queue.h"
+
+using namespace ns3;
+
+static Ptr<CsmaNetDevice>
+CreateCsmaDevice (Ptr<Node> node, Ptr<CsmaChannel> channel)
+{
+  Ptr<CsmaNetDevice> device = Create<CsmaNetDevice> (node);
+  device->Attach (channel);
+  Ptr<Queue> queue = Queue::CreateDefault ();
+  device->AddQueue (queue);
+  return device;
+}
+
+
+int main (int argc, char *argv[])
+{
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<Node> ();
+  Ptr<Node> n1 = Create<Node> (); 
+  Ptr<Node> n2 = Create<Node> (); 
+  Ptr<Node> n3 = Create<Node> ();
+
+  // create the shared medium used by all csma devices.
+  Ptr<CsmaChannel> channel = Create<CsmaChannel> (DataRate(5000000), MilliSeconds(2));
+
+  // use a helper function to connect our nodes to the shared channel.
+  Ptr<NetDevice> n0If = CreateCsmaDevice (n0, channel);
+  Ptr<NetDevice> n1If = CreateCsmaDevice (n1, channel);
+  Ptr<NetDevice> n2If = CreateCsmaDevice (n2, channel);
+  Ptr<NetDevice> n3If = CreateCsmaDevice (n3, channel);
+
+
+  // create the address which identifies n1 from n0
+  PacketSocketAddress n0ToN1;
+  n0ToN1.SetSingleDevice (n0If->GetIfIndex ());      // set outgoing interface for outgoing packets
+  n0ToN1.SetPhysicalAddress (n1If->GetAddress ()); // set destination address for outgoing packets
+  n0ToN1.SetProtocol (2);            // set arbitrary protocol for outgoing packets
+
+  // create the address which identifies n0 from n3
+  PacketSocketAddress n3ToN0;
+  n3ToN0.SetSingleDevice (n3If->GetIfIndex ());
+  n3ToN0.SetPhysicalAddress (n0If->GetAddress ());
+  n3ToN0.SetProtocol (3);
+  
+  // Create the OnOff application to send raw datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  // from n0 to n1
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    n0ToN1,
+    "Packet",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.0));
+  ooff->Stop (Seconds(10.0));
+
+  // Create a similar flow from n3 to n0, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    n3ToN0,
+    "Packet",
+    ConstantVariable(1), 
+    ConstantVariable(0));
+  // Start the application
+  ooff->Start(Seconds(1.1));
+  ooff->Stop (Seconds(10.0));
+ 
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the csma-packet-socket.tr file
+  AsciiTrace asciitrace ("csma-packet-socket.tr");
+  asciitrace.TraceAllNetDeviceRx ();
+  asciitrace.TraceAllQueues ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mixed-global-routing.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ */
+
+// This script exercises global routing code in a mixed point-to-point
+// and csma/cd environment
+//
+// Network topology
+//
+//  n0
+//     \ p-p
+//      \          (shared csma/cd)
+//       n2 -------------------------n3
+//      /            |        | 
+//     / p-p        n4        n5 ---------- n6
+//   n1                             p-p
+//
+// - CBR/UDP flows from n0 to n6
+// - Tracing of queues and packet receptions to file "mixed-global-routing.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/debug.h"
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/csma-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/csma-topology.h"
+#include "ns3/csma-ipv4-topology.h"
+#include "ns3/eui48-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/global-route-manager.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  DebugComponentEnable ("Object");
+  DebugComponentEnable ("Queue");
+  DebugComponentEnable ("DropTailQueue");
+  DebugComponentEnable ("Channel");
+  DebugComponentEnable ("PointToPointChannel");
+  DebugComponentEnable ("PointToPointNetDevice");
+  DebugComponentEnable ("GlobalRouter");
+  DebugComponentEnable ("GlobalRouteManager");
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind ()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below DefaultValue::Bind command tells the queue factory which 
+  // class to instantiate, when the queue factory is invoked in the 
+  // topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
+
+  // Allow the user to override any of the defaults and the above
+  // Bind ()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+  Ptr<Node> n4 = Create<InternetNode> (); 
+  Ptr<Node> n5 = Create<InternetNode> (); 
+  Ptr<Node> n6 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate (5000000), MilliSeconds (2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate (5000000), MilliSeconds (2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n5, n6, DataRate (1500000), MilliSeconds (10));
+
+  // We create the channels first without any IP addressing information
+  Ptr<CsmaChannel> channelc0 = 
+    CsmaTopology::CreateCsmaChannel(
+      DataRate(5000000), MilliSeconds(2));
+
+  uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channelc0,
+                                         Eui48Address("10:54:23:54:23:50"));
+  uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channelc0,
+                                         Eui48Address("10:54:23:54:23:51"));
+  uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n4, channelc0,
+                                         Eui48Address("10:54:23:54:23:52"));
+  uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n5, channelc0,
+                                         Eui48Address("10:54:23:54:23:53"));
+
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address ("10.1.1.1"),
+      n2, Ipv4Address ("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address ("10.1.2.1"),
+      n2, Ipv4Address ("10.1.2.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n5, Ipv4Address ("10.1.3.1"),
+      n6, Ipv4Address ("10.1.3.2"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n2, n2ifIndex, Ipv4Address("10.250.1.1"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n3, n3ifIndex, Ipv4Address("10.250.1.2"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n4, n4ifIndex, Ipv4Address("10.250.1.3"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n5, n5ifIndex, Ipv4Address("10.250.1.4"), Ipv4Mask("255.255.255.0"));
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress ("10.1.3.2", 80), 
+    "Udp",
+    ConstantVariable (1), 
+    ConstantVariable (0),
+    DataRate("300bps"),
+    50);
+  // Start the application
+  ooff->Start (Seconds (1.0));
+  ooff->Stop (Seconds (10.0));
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-global-routing.tr file
+  AsciiTrace asciitrace ("mixed-global-routing.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("mixed-global-routing.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-global-routing.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,183 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ *
+ * ns-2 simple.tcl script (ported from ns-2)
+ * Originally authored by Steve McCanne, 12/19/1996
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//  n0
+//     \ 5 Mb/s, 2ms
+//      \          1.5Mb/s, 10ms
+//       n2 -------------------------n3
+//      /
+//     / 5 Mb/s, 2ms
+//   n1
+//
+// - all links are point-to-point links with indicated one-way BW/delay
+// - CBR/UDP flows from n0 to n3, and from n3 to n1
+// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+//   (i.e., DataRate of 448,000 bps)
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "simple-global-routing.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/debug.h"
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/global-route-manager.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  DebugComponentEnable ("Object");
+  DebugComponentEnable ("Queue");
+  DebugComponentEnable ("DropTailQueue");
+  DebugComponentEnable ("Channel");
+  DebugComponentEnable ("PointToPointChannel");
+  DebugComponentEnable ("PointToPointNetDevice");
+  DebugComponentEnable ("GlobalRouter");
+  DebugComponentEnable ("GlobalRouteMaager");
+#endif
+
+  // Set up some default values for the simulation.  Use the DefaultValue::Bind ()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below Bind command tells the queue factory which class to
+  // instantiate, when the queue factory is invoked in the topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
+
+  // Allow the user to override any of the defaults and the above
+  // DefaultValue::Bind ()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  // Here, we will explicitly create four nodes.  In more sophisticated
+  // topologies, we could configure a node factory.
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate (5000000), MilliSeconds (2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate (5000000), MilliSeconds (2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n2, n3, DataRate (1500000), MilliSeconds (10));
+  
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address ("10.1.1.1"),
+      n2, Ipv4Address ("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address ("10.1.2.1"),
+      n2, Ipv4Address ("10.1.2.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n2, Ipv4Address ("10.1.3.1"),
+      n3, Ipv4Address ("10.1.3.2"));
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress ("10.1.3.2", 80), 
+    "Udp",
+    ConstantVariable (1), 
+    ConstantVariable (0));
+  // Start the application
+  ooff->Start (Seconds (1.0));
+  ooff->Stop (Seconds (10.0));
+
+  // Create a similar flow from n3 to n1, starting at time 1.1 seconds
+  ooff = Create<OnOffApplication> (
+    n3, 
+    InetSocketAddress ("10.1.2.1", 80),
+    "Udp",
+    ConstantVariable (1), 
+    ConstantVariable (0));
+  // Start the application
+  ooff->Start (Seconds (1.1));
+  ooff->Stop (Seconds (10.0));
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-global-routing.tr file
+  AsciiTrace asciitrace ("simple-global-routing.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("simple-global-routing.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+
+  return 0;
+}
--- a/examples/simple-point-to-point.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/examples/simple-point-to-point.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -57,8 +57,8 @@
 #include "ns3/internet-node.h"
 #include "ns3/point-to-point-channel.h"
 #include "ns3/point-to-point-net-device.h"
-#include "ns3/mac-address.h"
 #include "ns3/ipv4-address.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/ipv4.h"
 #include "ns3/socket.h"
 #include "ns3/ipv4-route.h"
@@ -72,6 +72,7 @@
 
   // Users may find it convenient to turn on explicit debugging
   // for selected modules; the below lines suggest how to do this
+  // remember to add #include "ns3/debug.h" before enabling these
 #if 0 
   DebugComponentEnable("Object");
   DebugComponentEnable("Queue");
@@ -87,12 +88,12 @@
 
   // The below Bind command tells the queue factory which class to
   // instantiate, when the queue factory is invoked in the topology code
-  Bind ("Queue", "DropTailQueue");
+  DefaultValue::Bind ("Queue", "DropTailQueue");
 
-  Bind ("OnOffApplicationPacketSize", "210");
-  Bind ("OnOffApplicationDataRate", "448kb/s");
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
 
-  //Bind ("DropTailQueue::m_maxPackets", 30);   
+  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
 
   // Allow the user to override any of the defaults and the above
   // Bind()s at run-time, via command-line arguments
@@ -144,8 +145,7 @@
   // 210 bytes at a rate of 448 Kb/s
   Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
     n0, 
-    Ipv4Address("10.1.3.2"), 
-    80, 
+    InetSocketAddress ("10.1.3.2", 80), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
@@ -156,8 +156,7 @@
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
   ooff = Create<OnOffApplication> (
     n3, 
-    Ipv4Address("10.1.2.1"), 
-    80, 
+    InetSocketAddress ("10.1.2.1", 80), 
     "Udp",
     ConstantVariable(1), 
     ConstantVariable(0));
--- a/examples/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ b/examples/wscript	Wed Sep 05 18:35:39 2007 +0100
@@ -1,14 +1,23 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-import Params
 
 def build(bld):
-    def create_ns_prog(name, source, deps=['core', 'common', 'simulator']):
-        obj = bld.create_obj('cpp', 'program')
-        obj.target = name
-        obj.uselib_local = ["ns3-%s" % dep for dep in deps]
-        obj.source = source
-        return obj
         
-    obj = create_ns_prog('simple-point-to-point', 'simple-point-to-point.cc', deps=['point-to-point', 'internet-node'])
-    obj = create_ns_prog('csma-cd-one-subnet', 'csma-cd-one-subnet.cc', deps=['csma-cd', 'internet-node'])
+    obj = bld.create_ns3_program('simple-global-routing',
+        ['point-to-point', 'internet-node', 'global-routing'])
+    obj.source = 'simple-global-routing.cc'
+
+    obj = bld.create_ns3_program('simple-point-to-point',
+        ['point-to-point', 'internet-node'])
+    obj.source = 'simple-point-to-point.cc'
 
+    obj = bld.create_ns3_program('csma-one-subnet',
+        ['csma', 'internet-node'])
+    obj.source = 'csma-one-subnet.cc'
+
+    obj = bld.create_ns3_program('csma-packet-socket',
+        ['csma', 'internet-node'])
+    obj.source = 'csma-packet-socket.cc'
+
+    obj = bld.create_ns3_program( 'mixed-global-routing',
+        ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
+    obj.source = 'mixed-global-routing.cc'
--- a/samples/main-default-value.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/samples/main-default-value.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -73,7 +73,7 @@
   // global variable and value (string) to overwrite the default.
   // Here, the default value of 33 for testInt1 is overwritten with 57
   // 
-  Bind("testInt1", "57");
+  DefaultValue::Bind("testInt1", "57");
 
   TestClass* testclass = new TestClass ();
   NS_DEBUG_UNCOND("TestBool1 default value (" << testclass->m_testBool1 << ")");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-packet-header.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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;
+}
--- a/samples/main-packet-printer.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/samples/main-packet-printer.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -90,15 +90,6 @@
   std::cout << std::endl;
 }
 
-// The below functions are used in place of default versions, in the
-// non-default case below.  For instance, DoPrintIpv4Header will print
-// out less IPv4 header information than the default print function
-void 
-DoPrintDefault (std::ostream &os,uint32_t packetUid, uint32_t size, 
-                std::string &name, struct PacketPrinter::FragmentInformation info)
-{
-  os << name <<" (size " << size << " trim_start " << info.start << " trim_end " << info.end << ")";
-}
 void
 DoPrintPayload (std::ostream & os,uint32_t packetUid,uint32_t size,
                 struct PacketPrinter::FragmentInformation info)
@@ -129,14 +120,10 @@
   // set a string separator automatically inserted
   // between each call to a printing function.
   printer.SetSeparator (" - ");
-  // set the default print function: invoked if no 
-  // specialized function has been provided for a header
-  // or trailer
-  printer.AddDefaultPrinter (MakeCallback (&DoPrintDefault));
   // set the payload print function
-  printer.AddPayloadPrinter (MakeCallback (&DoPrintPayload));
+  printer.SetPayloadPrinter (MakeCallback (&DoPrintPayload));
   // set the print function for the header type Ipv4Header.
-  printer.AddHeaderPrinter (MakeCallback (&DoPrintIpv4Header),
+  printer.SetHeaderPrinter (MakeCallback (&DoPrintIpv4Header),
                             MakeCallback (&DoPrintIpv4HeaderFragment));
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-packet-tag.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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/main-packet.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +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:
-  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 ()
-{}
-MyHeader::~MyHeader ()
-{}
-std::string 
-MyHeader::DoGetName (void) const
-{
-  return "MyHeader";
-}
-void 
-MyHeader::PrintTo (std::ostream &os) const
-{
-  os << "MyHeader data=" << m_data << std::endl;
-}
-uint32_t
-MyHeader::GetSerializedSize (void) const
-{
-  return 2;
-}
-void
-MyHeader::SerializeTo (Buffer::Iterator start) const
-{
-  // serialize in head of buffer
-  start.WriteHtonU16 (m_data);
-}
-uint32_t
-MyHeader::DeserializeFrom (Buffer::Iterator start)
-{
-  // deserialize from head of buffer
-  m_data = start.ReadNtohU16 ();
-  return GetSerializedSize ();
-}
-
-void 
-MyHeader::SetData (uint16_t data)
-{
-  m_data = data;
-}
-uint16_t 
-MyHeader::GetData (void) const
-{
-  return m_data;
-}
-
-/* A sample Tag implementation
- */
-struct MyTag {
-  uint16_t m_streamId;
-};
-
-static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
-
-
-static void
-Receive (Packet p)
-{
-  MyHeader my;
-  p.RemoveHeader (my);
-  std::cout << "received data=" << my.GetData () << std::endl;
-  struct MyTag myTag;
-  p.PeekTag (myTag);
-}
-
-
-int main (int argc, char *argv[])
-{
-  Packet p;
-  MyHeader my;
-  my.SetData (2);
-  std::cout << "send data=2" << std::endl;
-  p.AddHeader (my);
-  struct MyTag myTag;
-  myTag.m_streamId = 5;
-  p.AddTag (myTag);
-  Receive (p);
-  return 0;
-}
--- a/samples/main-random-topology.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/samples/main-random-topology.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -24,12 +24,12 @@
 
 int main (int argc, char *argv[])
 {
-  Bind ("RandomDiscPositionX", "100");
-  Bind ("RandomDiscPositionY", "50");
-  Bind ("RandomDiscPositionRho", "Uniform:0:30");
+  DefaultValue::Bind ("RandomDiscPositionX", "100");
+  DefaultValue::Bind ("RandomDiscPositionY", "50");
+  DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
 
-  Bind ("RandomTopologyPositionType", "RandomDiscPosition");
-  Bind ("RandomTopologyMobilityType", "StaticMobilityModel");
+  DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
+  DefaultValue::Bind ("RandomTopologyMobilityType", "StaticMobilityModel");
 
   CommandLine::Parse (argc, argv);
 
--- a/samples/main-simple.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/samples/main-simple.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -4,7 +4,9 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
 #include "ns3/nstime.h"
+#include "ns3/packet.h"
 
 using namespace ns3;
 
@@ -12,7 +14,7 @@
 GenerateTraffic (Ptr<Socket> socket, uint32_t size)
 {
   std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, tx bytes=" << size << std::endl;
-  socket->Send (0, size);
+  socket->Send (Packet (size));
   if (size > 0)
     {
       Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
@@ -24,15 +26,15 @@
 }
 
 static void
-SocketPrinter (Ptr<Socket> socket, uint32_t size, const Ipv4Address &from, uint16_t fromPort)
+SocketPrinter (Ptr<Socket> socket, const Packet &packet, const Address &from)
 {
-  std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << size << std::endl;
+  std::cout << "at=" << Simulator::Now ().GetSeconds () << "s, rx bytes=" << packet.GetSize () << std::endl;
 }
 
 static void
 PrintTraffic (Ptr<Socket> socket)
 {
-  socket->RecvDummy (MakeCallback (&SocketPrinter));
+  socket->SetRecvCallback (MakeCallback (&SocketPrinter));
 }
 
 void
@@ -44,10 +46,12 @@
   Ptr<SocketFactory> socketFactory = a->QueryInterface<SocketFactory> (iid);
 
   Ptr<Socket> sink = socketFactory->CreateSocket ();
-  sink->Bind (80);
+  InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), 80);
+  sink->Bind (local);
 
   Ptr<Socket> source = socketFactory->CreateSocket ();
-  source->Connect (Ipv4Address::GetLoopback (), 80);
+  InetSocketAddress remote = InetSocketAddress (Ipv4Address::GetLoopback (), 80);
+  source->Connect (remote);
 
   GenerateTraffic (source, 500);
   PrintTraffic (sink);
--- a/samples/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ b/samples/wscript	Wed Sep 05 18:35:39 2007 +0100
@@ -1,28 +1,43 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-import Params
 
 def build(bld):
-    def create_ns_prog(name, source, deps=['core', 'common', 'simulator']):
-        obj = bld.create_obj('cpp', 'program')
-        obj.target = name
-        obj.uselib_local = ["ns3-%s" % dep for dep in deps]
-        obj.source = source
-        return obj
-        
-    obj = create_ns_prog('main-debug', ['main-debug.cc', 'main-debug-other.cc'])
-    obj = create_ns_prog('main-callback', 'main-callback.cc')
-    obj = create_ns_prog('main-ptr', 'main-ptr.cc')
-    #obj = create_ns_prog('main-trace', 'main-trace.cc')
-    obj = create_ns_prog('main-simulator', 'main-simulator.cc')
-    obj = create_ns_prog('main-packet', 'main-packet.cc')
-    obj = create_ns_prog('main-test', 'main-test.cc')
-    obj = create_ns_prog('main-simple', 'main-simple.cc',
-                         deps=['node', 'internet-node', 'applications'])
-    #obj = create_ns_prog('main-simple-p2p', 'main-simple-p2p.cc', deps=['node', 'point-to-point'])
-    obj = create_ns_prog('main-default-value', 'main-default-value.cc',
-                         deps=['core', 'simulator', 'node', 'point-to-point'])
-    obj = create_ns_prog('main-grid-topology', 'main-grid-topology.cc',
-                         deps=['core', 'simulator', 'mobility', 'internet-node'])
-    obj = create_ns_prog('main-random-topology', 'main-random-topology.cc',
-                         deps=['core', 'simulator', 'mobility'])
+    obj = bld.create_ns3_program('main-debug')
+    obj.source = ['main-debug.cc', 'main-debug-other.cc']
+
+    obj = bld.create_ns3_program('main-callback')
+    obj.source = 'main-callback.cc'
+
+    obj = bld.create_ns3_program('main-ptr')
+    obj.source = 'main-ptr.cc'
+
+    obj = bld.create_ns3_program('main-simulator')
+    obj.source = 'main-simulator.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'
+
+    obj = bld.create_ns3_program('main-simple',
+                                 ['node', 'internet-node', 'applications'])
+    obj.source = 'main-simple.cc'
+
+    obj = bld.create_ns3_program('main-default-value',
+                                 ['core', 'simulator', 'node', 'point-to-point'])
+    obj.source = 'main-default-value.cc'
+
+    obj = bld.create_ns3_program('main-grid-topology',
+                                 ['core', 'simulator', 'mobility', 'internet-node'])
+    obj.source = 'main-grid-topology.cc'
+
+    obj = bld.create_ns3_program('main-random-topology',
+                                 ['core', 'simulator', 'mobility'])
+    obj.source = 'main-random-topology.cc'
+
--- a/src/applications/onoff-application.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/applications/onoff-application.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -22,7 +22,7 @@
 // George F. Riley, Georgia Tech, Spring 2007
 // Adapted from ApplicationOnOff in GTNetS.
 
-#include "ns3/ipv4-address.h"
+#include "ns3/address.h"
 #include "ns3/node.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
@@ -31,6 +31,7 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/default-value.h"
+#include "ns3/packet.h"
 #include "onoff-application.h"
 
 using namespace std;
@@ -47,22 +48,20 @@
 // Constructors
 
 OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Ipv4Address  rip,
-                                   uint16_t rport,
+                                   const Address &remote,
                                    std::string iid,
                                    const  RandomVariable& ontime,
                                    const  RandomVariable& offtime)
   :  Application(n),
      m_cbrRate (g_defaultRate.GetValue ())
 {
-  Construct (n, rip, rport, iid,
+  Construct (n, remote, iid,
              ontime, offtime, 
              g_defaultSize.GetValue ());
 }
 
 OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Ipv4Address  rip,
-                                   uint16_t rport,
+                                   const Address &remote,
                                    std::string iid,
                                    const  RandomVariable& ontime,
                                    const  RandomVariable& offtime,
@@ -71,22 +70,20 @@
   :  Application(n),
      m_cbrRate (rate)
 {
-  Construct (n, rip, rport, iid, 
+  Construct (n, remote, iid, 
              ontime, offtime, size);
 }
 
 void
 OnOffApplication::Construct (Ptr<Node> n, 
-                             const Ipv4Address  rip,
-                             uint16_t rport,
+                             const Address &remote,
                              std::string iid,
                              const  RandomVariable& onTime,
                              const  RandomVariable& offTime,
                              uint32_t size)
 {
   m_socket = 0;
-  m_peerIp = rip;
-  m_peerPort = rport;
+  m_peer = remote;
   m_connected = false;
   m_onTime = onTime.Copy ();
   m_offTime = offTime.Copy ();
@@ -144,7 +141,7 @@
       Ptr<SocketFactory> socketFactory = GetNode ()->QueryInterface<SocketFactory> (iid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind ();
-      m_socket->Connect (m_peerIp, m_peerPort);
+      m_socket->Connect (m_peer);
     }
   // Insure no pending event
   StopApplication();
@@ -209,7 +206,7 @@
 void OnOffApplication::SendPacket()
 {
   NS_ASSERT (m_sendEvent.IsExpired ());
-  m_socket->Send(0, m_pktSize);
+  m_socket->Send(Packet (m_pktSize));
   m_totBytes += m_pktSize;
   m_lastStartTime = Simulator::Now();
   m_residualBits = 0;
--- a/src/applications/onoff-application.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/applications/onoff-application.h	Wed Sep 05 18:35:39 2007 +0100
@@ -28,13 +28,13 @@
 #include "ns3/application.h"
 #include "ns3/event-id.h"
 #include "ns3/ptr.h"
+#include "ns3/data-rate.h"
 
 namespace ns3 {
 
-class Ipv4Address;
+class Address;
 class RandomVariable;
 class Socket;
-class DataRate;
 
 /**
  * \brief Generate traffic to a single destination according to an
@@ -52,23 +52,20 @@
 public:
   /**
    * \param n node associated to this application
-   * \param rip remote ip address
-   * \param rport remove port number
+   * \param remote remote ip address
    * \param iid
    * \param ontime on time random variable
    * \param offtime off time random variable
    */
   OnOffApplication(Ptr<Node> n,
-                   const Ipv4Address rip,
-                   uint16_t rport,
+                   const Address &remote,
                    std::string iid,
                    const RandomVariable& ontime,
                    const RandomVariable& offtime);
 
   /**
    * \param n node associated to this application
-   * \param rip remote ip address
-   * \param rport remove port number
+   * \param remote remote ip address
    * \param iid
    * \param ontime on time random variable
    * \param offtime off time random variable
@@ -76,8 +73,7 @@
    * \param size size of packets when sending data.
    */
   OnOffApplication(Ptr<Node> n,
-                   const Ipv4Address rip,
-                   uint16_t rport,
+                   const Address &remote,
                    std::string iid,
                    const RandomVariable& ontime,
                    const RandomVariable& offtime,
@@ -112,8 +108,7 @@
   virtual void StopApplication (void);     // Called at time specified by Stop
 
   void Construct (Ptr<Node> n,
-                  const Ipv4Address rip,
-                  uint16_t rport,
+                  const Address &remote,
                   std::string iid,
                   const RandomVariable& ontime,
                   const RandomVariable& offtime,
@@ -126,8 +121,7 @@
   void SendPacket();
 
   Ptr<Socket>     m_socket;       // Associated socket
-  Ipv4Address     m_peerIp;       // Peer IP address
-  uint16_t        m_peerPort;     // Peer port
+  Address         m_peer;         // Peer address
   bool            m_connected;    // True if connected
   RandomVariable* m_onTime;       // rng for On Time
   RandomVariable* m_offTime;      // rng for Off Time
--- a/src/applications/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/applications/wscript	Wed Sep 05 18:35:39 2007 +0100
@@ -1,10 +1,7 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    obj = bld.create_obj('cpp', 'shlib')
-    obj.name = 'ns3-applications'
-    obj.target = obj.name
-    obj.uselib_local = ['ns3-node']
+    obj = bld.create_ns3_module('applications', ['node'])
     obj.source = [
         'onoff-application.cc',
         ]
--- a/src/common/array-trace-resolver.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/array-trace-resolver.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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
@@ -81,51 +53,37 @@
    */
   ArrayTraceResolver (TraceContext const &context,
                       Callback<uint32_t> getSize, 
-                      Callback<T *, uint32_t> get);
+                      Callback<T, uint32_t> get);
 private:
   virtual TraceResolverList DoLookup (std::string id) const;
   Callback<uint32_t> m_getSize;
-  Callback<T *, uint32_t> m_get;
+  Callback<T, uint32_t> m_get;
 };
 }//namespace ns3
 
 namespace ns3 {
 
-template <typename T>
-ArrayTraceResolver<T>::Index::Index ()
-  : m_index ()
-{}
-template <typename T>
-ArrayTraceResolver<T>::Index::Index (uint32_t index)
-  : m_index (index)
-{}
-template <typename T>
-ArrayTraceResolver<T>::Index::operator uint32_t ()
-{
-  return m_index;
-}
-
-template <typename T>
-ArrayTraceResolver<T>::ArrayTraceResolver (TraceContext const &context,
-                                           Callback<uint32_t> getSize, 
-                                           Callback<T *, uint32_t> get)
+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 == "*")
   {
     for (uint32_t i = 0; i < m_getSize (); i++)
     {
-	  TraceContext context = GetContext ();
-      typename ArrayTraceResolver<T>::Index index = typename ArrayTraceResolver<T>::Index (i);
-	  context.Add (index);
-	  list.push_back (m_get (i)->CreateTraceResolver (context));
+      TraceContext context = GetContext ();
+      INDEX index = i;
+      context.Add (index);
+      list.push_back (m_get (i)->CreateTraceResolver (context));
     }
   }
   return list;
--- a/src/common/buffer.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/buffer.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -410,8 +410,8 @@
   return tmp;
 }
 
-void
-Buffer::TransformIntoRealBuffer (void) const
+Buffer 
+Buffer::CreateFullCopy (void) const
 {
   if (m_zeroAreaSize != 0) 
     {
@@ -428,8 +428,16 @@
       Buffer::Iterator i = tmp.End ();
       i.Prev (dataEnd);
       i.Write (m_data->m_data+m_data->m_initialStart,dataEnd);
-      *const_cast<Buffer *> (this) = tmp;
+      return tmp;
     }
+  return *this;
+}
+
+void
+Buffer::TransformIntoRealBuffer (void) const
+{
+  Buffer tmp = CreateFullCopy ();
+  *const_cast<Buffer *> (this) = tmp;
 }
 
 
--- a/src/common/buffer.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/buffer.h	Wed Sep 05 18:35:39 2007 +0100
@@ -320,7 +320,7 @@
    */
   inline Buffer::Iterator End (void) const;
 
-  void TransformIntoRealBuffer (void) const;
+  Buffer CreateFullCopy (void) const;
 
   inline Buffer (Buffer const &o);
   inline Buffer &operator = (Buffer const &o);
@@ -343,6 +343,7 @@
   };
 
   inline uint8_t *GetStart (void) const;
+  void TransformIntoRealBuffer (void) const;
   static void Recycle (struct Buffer::BufferData *data);
   static struct Buffer::BufferData *Create (void);
   static struct Buffer::BufferData *Allocate (uint32_t size, uint32_t start);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/chunk-registry.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +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;
-}
-
-}; // namespace ns3
--- a/src/common/chunk.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +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"
-
-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);
-
-}; // namespace ns3
-
-#endif /* CHUNK_H */
--- a/src/common/composite-trace-resolver.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/composite-trace-resolver.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/composite-trace-resolver.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ /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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/header.h	Wed Sep 05 18:35:39 2007 +0100
@@ -22,7 +22,29 @@
 #ifndef HEADER_H
 #define HEADER_H
 
-#include "chunk.h"
+#include "chunk-registry.h"
+
+/**
+ * \relates ns3::Header
+ * \brief this macro should be instantiated exactly once for each
+ *        new type of Header
+ *
+ * This macro will ensure that your new Header type is registered
+ * within the packet header 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_HEADER_ENSURE_REGISTERED(x)         \
+static class thisisaveryverylongclassname ##x  \
+{                                              \
+ public:                                       \
+  thisisaveryverylongclassname ##x ()          \
+    { uint32_t uid; uid = x::GetUid ();}       \
+} g_thisisanotherveryveryverylongname ## x;
+
 
 namespace ns3 {
 
@@ -30,68 +52,64 @@
  * \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
+ * 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.
+ *
+ * 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 ();
-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;
+class Header 
+{
+protected:
+  template <typename T>
+  static uint32_t AllocateUid (std::string uuid);
 };
 
-}; // namespace ns3
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+uint32_t 
+Header::AllocateUid (std::string uuid)
+{
+  return ChunkRegistry::RegisterHeader<T> (uuid);
+}
+
+} // namespace ns3
 
 #endif /* HEADER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/packet-metadata-test.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,683 @@
+/* -*- 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>
+ */
+#ifdef RUN_SELF_TESTS
+
+#include <stdarg.h>
+#include <iostream>
+#include <sstream>
+#include "ns3/test.h"
+#include "header.h"
+#include "trailer.h"
+#include "packet.h"
+#include "packet-metadata.h"
+#include "packet-printer.h"
+
+namespace ns3 {
+
+template <int N>
+class HistoryHeader : public Header
+{
+public:
+  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:
+  bool m_ok;
+};
+
+template <int N>
+uint32_t
+HistoryHeader<N>::GetUid (void)
+{
+  std::ostringstream oss;
+  oss << N << "HistoryHeader.ns3";
+  static uint32_t uid = AllocateUid<HistoryHeader<N> > (oss.str());
+  return uid;
+}
+
+template <int N>
+HistoryHeader<N>::HistoryHeader ()
+  : m_ok (false)
+{}
+
+template <int N>
+bool 
+HistoryHeader<N>::IsOk (void) const
+{
+  return m_ok;
+}
+
+template <int N>
+std::string 
+HistoryHeader<N>::GetName (void) const
+{
+  std::ostringstream oss;
+  oss << N;
+  return oss.str ();
+}
+
+template <int N>
+void 
+HistoryHeader<N>::Print (std::ostream &os) const
+{
+  NS_ASSERT (false);
+}
+template <int N>
+uint32_t 
+HistoryHeader<N>::GetSerializedSize (void) const
+{
+  return N;
+}
+template <int N>
+void 
+HistoryHeader<N>::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (N, N);
+}
+template <int N>
+uint32_t
+HistoryHeader<N>::Deserialize (Buffer::Iterator start)
+{
+  m_ok = true;
+  for (int i = 0; i < N; i++)
+    {
+      if (start.ReadU8 () != N)
+        {
+          m_ok = false;
+        }
+    }
+  return N;
+}
+
+template <int N>
+class HistoryTrailer : public Trailer
+{
+public:
+  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:
+  bool m_ok;
+};
+
+template <int N>
+uint32_t
+HistoryTrailer<N>::GetUid (void)
+{
+  std::ostringstream oss;
+  oss << N << "HistoryTrailer.ns3";
+  static uint32_t uid = AllocateUid<HistoryTrailer<N> > (oss.str ());
+  return uid;
+}
+
+
+template <int N>
+HistoryTrailer<N>::HistoryTrailer ()
+  : m_ok (false)
+{}
+
+template <int N>
+bool
+HistoryTrailer<N>::IsOk (void) const
+{
+  return m_ok;
+}
+
+template <int N>
+std::string 
+HistoryTrailer<N>::GetName (void) const
+{
+  std::ostringstream oss;
+  oss << N;
+  return oss.str ();
+}
+template <int N>
+void 
+HistoryTrailer<N>::Print (std::ostream &os) const
+{
+  NS_ASSERT (false);
+}
+template <int N>
+uint32_t 
+HistoryTrailer<N>::GetSerializedSize (void) const
+{
+  return N;
+}
+template <int N>
+void 
+HistoryTrailer<N>::Serialize (Buffer::Iterator start) const
+{
+  start.Prev (N);
+  start.WriteU8 (N, N);
+}
+template <int N>
+uint32_t
+HistoryTrailer<N>::Deserialize (Buffer::Iterator start)
+{
+  m_ok = true;
+  start.Prev (N);
+  for (int i = 0; i < N; i++)
+    {
+      if (start.ReadU8 () != N)
+        {
+          m_ok = false;
+        }
+    }
+  return N;
+}
+
+
+
+class PacketMetadataTest : public Test {
+public:
+  PacketMetadataTest ();
+  virtual ~PacketMetadataTest ();
+  bool CheckHistory (Packet p, const char *file, int line, uint32_t n, ...);
+  virtual bool RunTests (void);
+private:
+  template <int N>
+  void PrintHeader (std::ostream &os, uint32_t packetUid, uint32_t size, const HistoryHeader<N> *header);
+  template <int N>
+  void PrintTrailer (std::ostream &os, uint32_t packetUid, uint32_t size, const HistoryTrailer<N> *trailer);
+  void PrintFragment (std::ostream &os,uint32_t packetUid,
+                      uint32_t size,std::string & name, 
+                      struct PacketPrinter::FragmentInformation info);
+  void PrintPayload (std::ostream &os,uint32_t packetUid,
+                     uint32_t size,
+                     struct PacketPrinter::FragmentInformation info);
+  template <int N>
+  void RegisterHeader (void);
+  template <int N>
+  void RegisterTrailer (void);
+  void CleanupPrints (void);
+  Packet DoAddHeader (Packet p);
+  bool Check (const char *file, int line, std::list<int> expected);
+
+
+  bool m_headerError;
+  bool m_trailerError;
+  std::list<int> m_prints;
+  PacketPrinter m_printer;
+};
+
+PacketMetadataTest::PacketMetadataTest ()
+  : Test ("PacketMetadata")
+{
+  m_printer.SetPayloadPrinter (MakeCallback (&PacketMetadataTest::PrintPayload, this));
+  m_printer.SetSeparator ("");
+}
+
+PacketMetadataTest::~PacketMetadataTest ()
+{}
+
+template <int N>
+void 
+PacketMetadataTest::RegisterHeader (void)
+{
+  static bool registered = false;
+  if (!registered)
+    {
+      m_printer.SetHeaderPrinter (MakeCallback (&PacketMetadataTest::PrintHeader<N>, this),
+                                  MakeCallback (&PacketMetadataTest::PrintFragment, this));
+      registered = true;
+    }
+}
+
+template <int N>
+void 
+PacketMetadataTest::RegisterTrailer (void)
+{
+  static bool registered = false;
+  if (!registered)
+    {
+      m_printer.SetTrailerPrinter (MakeCallback (&PacketMetadataTest::PrintTrailer<N>, this),
+                                   MakeCallback (&PacketMetadataTest::PrintFragment, this));
+      registered = true;
+    }
+}
+
+
+template <int N>
+void 
+PacketMetadataTest::PrintHeader (std::ostream &os, uint32_t packetUid, uint32_t size, 
+                                const HistoryHeader<N> *header)
+{
+  if (!header->IsOk ())
+    {
+      m_headerError = true;
+    }
+  m_prints.push_back (N);
+}
+
+template <int N>
+void 
+PacketMetadataTest::PrintTrailer (std::ostream &os, uint32_t packetUid, uint32_t size, 
+                                 const HistoryTrailer<N> *trailer)
+{
+  if (!trailer->IsOk ())
+    {
+      m_trailerError = true;
+    }
+  m_prints.push_back (N);
+}
+void 
+PacketMetadataTest::PrintFragment (std::ostream &os,uint32_t packetUid,
+                                  uint32_t size,std::string & name, 
+                                  struct PacketPrinter::FragmentInformation info)
+{
+  m_prints.push_back (size - (info.end + info.start));
+}
+void 
+PacketMetadataTest::PrintPayload (std::ostream &os,uint32_t packetUid,
+                                 uint32_t size,
+                                 struct PacketPrinter::FragmentInformation info)
+{
+  m_prints.push_back (size - (info.end + info.start));
+}
+
+
+void 
+PacketMetadataTest::CleanupPrints (void)
+{
+  m_prints.clear ();
+}
+
+bool
+PacketMetadataTest::Check (const char *file, int line, std::list<int> expected)
+{
+  if (m_headerError)
+    {
+      Failure () << "PacketMetadata header error. file=" << file 
+                << ", line=" << line << std::endl;
+      return false;
+    }
+  if (m_trailerError)
+    {
+      Failure () << "PacketMetadata trailer error. file=" << file 
+                << ", line=" << line << std::endl;
+      return false;
+    }
+  if (expected.size () != m_prints.size ())
+    {
+      goto error;
+    }
+  for (std::list<int>::iterator i = m_prints.begin (),
+         j = expected.begin (); 
+       i != m_prints.end (); i++, j++)
+    {
+      NS_ASSERT (j != expected.end ());
+      if (*j != *i)
+        {
+          goto error;
+        }
+    }
+  return true;
+ error:
+  Failure () << "PacketMetadata error. file="<< file 
+            << ", line=" << line << ", got:\"";
+  for (std::list<int>::iterator i = m_prints.begin (); 
+       i != m_prints.end (); i++)
+    {
+      Failure () << *i << ", ";
+    }
+  Failure () << "\", expected: \"";
+  for (std::list<int>::iterator j = expected.begin ();
+       j != expected.end (); j++)
+    {
+      Failure () << *j << ", ";
+    }
+  Failure () << "\"" << std::endl;
+  return false;
+}
+
+bool 
+PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t n, ...)
+{
+  m_headerError = false;
+  m_trailerError = false;
+  std::list<int> expected;
+  va_list ap;
+  va_start (ap, n);
+  for (uint32_t j = 0; j < n; j++)
+    {
+      int v = va_arg (ap, int);
+      expected.push_back (v);
+    }
+  va_end (ap);
+
+  m_printer.PrintForward ();
+  p.Print (Failure (), m_printer);
+  bool ok = Check (file, line, expected);
+  CleanupPrints ();
+  if (!ok)
+    {
+      return false;
+    }
+
+  m_printer.PrintBackward ();
+  p.Print (Failure (), m_printer);
+  expected.reverse ();
+  ok = Check (file, line, expected);
+  CleanupPrints ();
+  return ok;
+}
+
+#define ADD_HEADER(p, n)                        \
+  {                                             \
+    HistoryHeader<n> header;                    \
+    RegisterHeader<n> ();                       \
+    p.AddHeader (header);                       \
+  }
+#define ADD_TRAILER(p, n)                       \
+  {                                             \
+    HistoryTrailer<n> trailer;                  \
+    RegisterTrailer<n> ();                      \
+    p.AddTrailer (trailer);                     \
+  }
+#define REM_HEADER(p, n)                        \
+  {                                             \
+    HistoryHeader<n> header;                    \
+    RegisterHeader<n> ();                       \
+    p.RemoveHeader (header);                    \
+  }
+#define REM_TRAILER(p, n)                       \
+  {                                             \
+    HistoryTrailer<n> trailer;                  \
+    RegisterTrailer<n> ();                      \
+    p.RemoveTrailer (trailer);                  \
+  }
+#define CHECK_HISTORY(p, ...)                   \
+  {                                             \
+    if (!CheckHistory (p, __FILE__,             \
+                      __LINE__, __VA_ARGS__))   \
+      {                                         \
+        ok = false;                             \
+      }                                         \
+    Buffer buffer;                              \
+    buffer = p.Serialize ();                    \
+    Packet otherPacket;                         \
+    otherPacket.Deserialize  (buffer);          \
+    if (!CheckHistory (otherPacket, __FILE__,   \
+                      __LINE__, __VA_ARGS__))   \
+      {                                         \
+        ok = false;                             \
+      }                                         \
+  }
+
+
+Packet 
+PacketMetadataTest::DoAddHeader (Packet p)
+{
+  ADD_HEADER (p, 10);
+  return p;
+}
+
+bool
+PacketMetadataTest::RunTests (void)
+{
+  bool ok = true;
+
+  PacketMetadata::Enable ();
+
+  Packet p = Packet (0);
+  Packet p1 = Packet (0);
+
+  p = Packet (10);
+  ADD_TRAILER (p, 100);
+  CHECK_HISTORY (p, 2, 10, 100);
+
+  p = Packet (10);
+  ADD_HEADER (p, 1);
+  ADD_HEADER (p, 2);
+  ADD_HEADER (p, 3);
+  CHECK_HISTORY (p, 4, 
+                 3, 2, 1, 10);
+  ADD_HEADER (p, 5);
+  CHECK_HISTORY (p, 5, 
+                 5, 3, 2, 1, 10);
+  ADD_HEADER (p, 6);
+  CHECK_HISTORY (p, 6, 
+                 6, 5, 3, 2, 1, 10);
+
+  p = Packet (10);
+  ADD_HEADER (p, 1);
+  ADD_HEADER (p, 2);
+  ADD_HEADER (p, 3);
+  REM_HEADER (p, 3);
+  CHECK_HISTORY (p, 3, 
+                 2, 1, 10);
+
+  p = Packet (10);
+  ADD_HEADER (p, 1);
+  ADD_HEADER (p, 2);
+  ADD_HEADER (p, 3);
+  REM_HEADER (p, 3);
+  REM_HEADER (p, 2);
+  CHECK_HISTORY (p, 2, 
+                 1, 10);
+
+  p = Packet (10);
+  ADD_HEADER (p, 1);
+  ADD_HEADER (p, 2);
+  ADD_HEADER (p, 3);
+  REM_HEADER (p, 3);
+  REM_HEADER (p, 2);
+  REM_HEADER (p, 1);
+  CHECK_HISTORY (p, 1, 10);
+
+  p = Packet (10);
+  ADD_HEADER (p, 1);
+  ADD_HEADER (p, 2);
+  ADD_HEADER (p, 3);
+  p1 = p;
+  REM_HEADER (p1, 3);
+  REM_HEADER (p1, 2);
+  REM_HEADER (p1, 1);
+  CHECK_HISTORY (p1, 1, 10);
+  CHECK_HISTORY (p, 4, 
+                 3, 2, 1, 10);
+  ADD_HEADER (p1, 1);
+  ADD_HEADER (p1, 2);
+  CHECK_HISTORY (p1, 3, 
+                 2, 1, 10);
+  CHECK_HISTORY (p, 4, 
+                 3, 2, 1, 10);
+  ADD_HEADER (p, 3);
+  CHECK_HISTORY (p, 5, 
+                 3, 3, 2, 1, 10);
+  ADD_TRAILER (p, 4);
+  CHECK_HISTORY (p, 6, 
+                 3, 3, 2, 1, 10, 4);
+  ADD_TRAILER (p, 5);
+  CHECK_HISTORY (p, 7, 
+                 3, 3, 2, 1, 10, 4, 5);
+  REM_HEADER (p, 3);
+  CHECK_HISTORY (p, 6, 
+                 3, 2, 1, 10, 4, 5);
+  REM_TRAILER (p, 5);
+  CHECK_HISTORY (p, 5, 
+                 3, 2, 1, 10, 4);
+  p1 = p;
+  REM_TRAILER (p, 4);
+  CHECK_HISTORY (p, 4, 
+                 3, 2, 1, 10);
+  CHECK_HISTORY (p1, 5, 
+                 3, 2, 1, 10, 4);
+  p1.RemoveAtStart (3);
+  CHECK_HISTORY (p1, 4, 
+                 2, 1, 10, 4);
+  p1.RemoveAtStart (1);
+  CHECK_HISTORY (p1, 4, 
+                 1, 1, 10, 4);
+  p1.RemoveAtStart (1);
+  CHECK_HISTORY (p1, 3, 
+                 1, 10, 4);
+  p1.RemoveAtEnd (4);
+  CHECK_HISTORY (p1, 2, 
+                 1, 10);
+  p1.RemoveAtStart (1);
+  CHECK_HISTORY (p1, 1, 10);
+
+  p = Packet (10);
+  ADD_HEADER (p, 8);
+  ADD_TRAILER (p, 8);
+  ADD_TRAILER (p, 8);
+  p.RemoveAtStart (8+10+8);
+  CHECK_HISTORY (p, 1, 8);
+
+  p = Packet (10);
+  ADD_HEADER (p, 10);
+  ADD_HEADER (p, 8);
+  ADD_TRAILER (p, 6);
+  ADD_TRAILER (p, 7);
+  ADD_TRAILER (p, 9);
+  p.RemoveAtStart (5);
+  p.RemoveAtEnd (12);
+  CHECK_HISTORY (p, 5, 3, 10, 10, 6, 4);
+
+  p = Packet (10);
+  ADD_HEADER (p, 10);
+  ADD_TRAILER (p, 6);
+  p.RemoveAtEnd (18);
+  ADD_TRAILER (p, 5);
+  ADD_HEADER (p, 3);
+  CHECK_HISTORY (p, 3, 3, 8, 5);
+  p.RemoveAtStart (12);
+  CHECK_HISTORY (p, 1, 4);
+  p.RemoveAtEnd (2);
+  CHECK_HISTORY (p, 1, 2);
+  ADD_HEADER (p, 10);
+  CHECK_HISTORY (p, 2, 10, 2);
+  p.RemoveAtEnd (5);
+  CHECK_HISTORY (p, 1, 7);
+
+  Packet p2 = Packet (0);
+  Packet p3 = Packet (0);
+
+  p = Packet (40);
+  ADD_HEADER (p, 5);
+  ADD_HEADER (p, 8);
+  CHECK_HISTORY (p, 3, 8, 5, 40);
+  p1 = p.CreateFragment (0, 5);
+  p2 = p.CreateFragment (5, 5);
+  p3 = p.CreateFragment (10, 43);
+  CHECK_HISTORY (p1, 1, 5);
+  CHECK_HISTORY (p2, 2, 3, 2);
+  CHECK_HISTORY (p3, 2, 3, 40);
+  p1.AddAtEnd (p2);
+  CHECK_HISTORY (p1, 2, 8, 2);
+  CHECK_HISTORY (p2, 2, 3, 2);
+  p1.AddAtEnd (p3);
+  CHECK_HISTORY (p1, 3, 8, 5, 40);
+  CHECK_HISTORY (p2, 2, 3, 2);
+  CHECK_HISTORY (p3, 2, 3, 40);
+  p1 = p.CreateFragment (0, 5);
+  CHECK_HISTORY (p1, 1, 5);
+
+  p3 = Packet (50);
+  ADD_HEADER (p3, 8);
+  CHECK_HISTORY (p3, 2, 8, 50);
+  CHECK_HISTORY (p1, 1, 5);
+  p1.AddAtEnd (p3);
+  CHECK_HISTORY (p1, 3, 5, 8, 50);
+  ADD_HEADER (p1, 5);
+  CHECK_HISTORY (p1, 4, 5, 5, 8, 50);
+  ADD_TRAILER (p1, 2);
+  CHECK_HISTORY (p1, 5, 5, 5, 8, 50, 2);
+  REM_HEADER (p1, 5);
+  CHECK_HISTORY (p1, 4, 5, 8, 50, 2);
+  p1.RemoveAtEnd (60);
+  CHECK_HISTORY (p1, 1, 5);
+  p1.AddAtEnd (p2);
+  CHECK_HISTORY (p1, 2, 8, 2);
+  CHECK_HISTORY (p2, 2, 3, 2);
+
+  p3 = Packet (40);
+  ADD_HEADER (p3, 5);
+  ADD_HEADER (p3, 5);
+  CHECK_HISTORY (p3, 3, 5, 5, 40);
+  p1 = p3.CreateFragment (0, 5);
+  p2 = p3.CreateFragment (5, 5);
+  CHECK_HISTORY (p1, 1, 5);
+  CHECK_HISTORY (p2, 1, 5);
+  p1.AddAtEnd (p2);
+  CHECK_HISTORY (p1, 2, 5, 5);
+
+  p = Packet (0);
+  CHECK_HISTORY (p, 0);
+
+  p3 = Packet (0);
+  ADD_HEADER (p3, 5);
+  ADD_HEADER (p3, 5);
+  CHECK_HISTORY (p3, 2, 5, 5);
+  p1 = p3.CreateFragment (0, 4);
+  p2 = p3.CreateFragment (9, 1);
+  CHECK_HISTORY (p1, 1, 4);
+  CHECK_HISTORY (p2, 1, 1);
+  p1.AddAtEnd (p2);
+  CHECK_HISTORY (p1, 2, 4, 1);
+
+
+  p = Packet (2000);
+  CHECK_HISTORY (p, 1, 2000);
+  
+  p = Packet ();
+  ADD_TRAILER (p, 10);
+  ADD_HEADER (p, 5);
+  p1 = p.CreateFragment (0, 8);
+  p2 = p.CreateFragment (8, 7);
+  p1.AddAtEnd (p2);
+  CHECK_HISTORY (p, 2, 5, 10);
+
+  p = Packet ();
+  ADD_TRAILER (p, 10);
+  REM_TRAILER (p, 10);
+  ADD_TRAILER (p, 10);
+  CHECK_HISTORY (p, 1, 10);
+
+  p = Packet ();
+  ADD_HEADER (p, 10);
+  REM_HEADER (p, 10);
+  ADD_HEADER (p, 10);
+  CHECK_HISTORY (p, 1, 10);
+
+  p = Packet ();
+  ADD_HEADER (p, 10);
+  p = DoAddHeader (p);
+  CHECK_HISTORY (p, 2, 10, 10);
+
+  return ok;
+}
+
+static PacketMetadataTest g_packetHistoryTest;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- a/src/common/packet-metadata.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet-metadata.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -1,7 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2006,2007 INRIA
- * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -24,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");
 
@@ -965,19 +964,13 @@
   NS_ASSERT (leftToRemove == 0);
 }
 
-void 
-PacketMetadata::PrintDefault (std::ostream &os, Buffer buffer) const
-{
-  Print (os, buffer, PacketPrinter::GetDefault ());
-}
-
 uint32_t
 PacketMetadata::DoPrint (const struct PacketMetadata::SmallItem *item, 
                          const struct PacketMetadata::ExtraItem *extraItem,
                          Buffer data, uint32_t offset, const PacketPrinter &printer,
                          std::ostream &os) const
 {
-  uint32_t uid = item->typeUid & 0xfffffffe;
+  uint32_t uid = (item->typeUid & 0xfffffffe) >> 1;
   if (uid == 0)
     {
       // payload.
@@ -992,13 +985,13 @@
                                   extraItem->fragmentStart, 
                                   item->size - extraItem->fragmentEnd);
     }
-  else if (PacketPrinter::IsHeader (uid))
+  else if (ChunkRegistry::IsHeader (uid))
     {
       ns3::Buffer::Iterator j = data.Begin ();
       j.Next (offset);
       printer.PrintChunk (uid, j, os, extraItem->packetUid, item->size);
     }
-  else if (PacketPrinter::IsTrailer (uid))
+  else if (ChunkRegistry::IsTrailer (uid))
     {
       ns3::Buffer::Iterator j = data.End ();
       j.Prev (data.GetSize () - (offset + item->size));
@@ -1094,629 +1087,145 @@
     }
 }
 
-
-
-}; // namespace ns3
-
-#include <stdarg.h>
-#include <iostream>
-#include <sstream>
-#include "ns3/test.h"
-#include "header.h"
-#include "trailer.h"
-#include "packet.h"
-
-namespace ns3 {
-
-template <int N>
-class HistoryHeader : public Header
-{
-public:
-  HistoryHeader ();
-  bool IsOk (void) const;
-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;
-};
-
-template <int N>
-HistoryHeader<N>::HistoryHeader ()
-  : m_ok (false)
-{}
-
-template <int N>
-bool 
-HistoryHeader<N>::IsOk (void) const
-{
-  return m_ok;
-}
-
-template <int N>
-std::string 
-HistoryHeader<N>::DoGetName (void) const
-{
-  std::ostringstream oss;
-  oss << N;
-  return oss.str ();
-}
-
-template <int N>
-void 
-HistoryHeader<N>::PrintTo (std::ostream &os) const
-{
-  NS_ASSERT (false);
-}
-template <int N>
 uint32_t 
-HistoryHeader<N>::GetSerializedSize (void) const
-{
-  return N;
-}
-template <int N>
-void 
-HistoryHeader<N>::SerializeTo (Buffer::Iterator start) const
-{
-  start.WriteU8 (N, N);
-}
-template <int N>
-uint32_t
-HistoryHeader<N>::DeserializeFrom (Buffer::Iterator start)
-{
-  m_ok = true;
-  for (int i = 0; i < N; i++)
-    {
-      if (start.ReadU8 () != N)
-        {
-          m_ok = false;
-        }
-    }
-  return N;
-}
-
-template <int N>
-class HistoryTrailer : public Trailer
-{
-public:
-  HistoryTrailer ();
-  bool IsOk (void) const;
-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;
-};
-
-template <int N>
-HistoryTrailer<N>::HistoryTrailer ()
-  : m_ok (false)
-{}
-
-template <int N>
-bool
-HistoryTrailer<N>::IsOk (void) const
-{
-  return m_ok;
-}
-
-template <int N>
-std::string 
-HistoryTrailer<N>::DoGetName (void) const
-{
-  std::ostringstream oss;
-  oss << N;
-  return oss.str ();
-}
-template <int N>
-void 
-HistoryTrailer<N>::PrintTo (std::ostream &os) const
+PacketMetadata::GetSerializedSize (void) const
 {
-  NS_ASSERT (false);
-}
-template <int N>
-uint32_t 
-HistoryTrailer<N>::GetSerializedSize (void) const
-{
-  return N;
-}
-template <int N>
-void 
-HistoryTrailer<N>::SerializeTo (Buffer::Iterator start) const
-{
-  start.Prev (N);
-  start.WriteU8 (N, N);
-}
-template <int N>
-uint32_t
-HistoryTrailer<N>::DeserializeFrom (Buffer::Iterator start)
-{
-  m_ok = true;
-  start.Prev (N);
-  for (int i = 0; i < N; i++)
+  uint32_t totalSize = 0;
+  totalSize += 4;
+  if (!m_enable)
     {
-      if (start.ReadU8 () != N)
-        {
-          m_ok = false;
-        }
+      return totalSize;
     }
-  return N;
-}
-
-
-
-class PacketMetadataTest : public Test {
-public:
-  PacketMetadataTest ();
-  virtual ~PacketMetadataTest ();
-  bool CheckHistory (Packet p, const char *file, int line, uint32_t n, ...);
-  virtual bool RunTests (void);
-private:
-  template <int N>
-  void PrintHeader (std::ostream &os, uint32_t packetUid, uint32_t size, const HistoryHeader<N> *header);
-  template <int N>
-  void PrintTrailer (std::ostream &os, uint32_t packetUid, uint32_t size, const HistoryTrailer<N> *trailer);
-  void PrintFragment (std::ostream &os,uint32_t packetUid,
-                      uint32_t size,std::string & name, 
-                      struct PacketPrinter::FragmentInformation info);
-  void PrintDefault (std::ostream& os,uint32_t packetUid,
-                     uint32_t size,std::string& name,
-                     struct PacketPrinter::FragmentInformation info);
-  void PrintPayload (std::ostream &os,uint32_t packetUid,
-                     uint32_t size,
-                     struct PacketPrinter::FragmentInformation info);
-  template <int N>
-  void RegisterHeader (void);
-  template <int N>
-  void RegisterTrailer (void);
-  void CleanupPrints (void);
-  bool Check (const char *file, int line, std::list<int> expected);
-
-
-  bool m_headerError;
-  bool m_trailerError;
-  std::list<int> m_prints;
-  PacketPrinter m_printer;
-};
-
-PacketMetadataTest::PacketMetadataTest ()
-  : Test ("PacketMetadata")
-{
-  m_printer.AddPayloadPrinter (MakeCallback (&PacketMetadataTest::PrintPayload, this));
-  m_printer.AddDefaultPrinter (MakeCallback (&PacketMetadataTest::PrintDefault, this));
-}
-
-PacketMetadataTest::~PacketMetadataTest ()
-{}
-
-template <int N>
-void 
-PacketMetadataTest::RegisterHeader (void)
-{
-  static bool registered = false;
-  if (!registered)
+  struct PacketMetadata::SmallItem item;
+  struct PacketMetadata::ExtraItem extraItem;
+  uint32_t current = m_head;
+  while (current != 0xffff)
     {
-      m_printer.AddHeaderPrinter (MakeCallback (&PacketMetadataTest::PrintHeader<N>, this),
-                                  MakeCallback (&PacketMetadataTest::PrintFragment, this));
-      registered = true;
-    }
-}
-
-template <int N>
-void 
-PacketMetadataTest::RegisterTrailer (void)
-{
-  static bool registered = false;
-  if (!registered)
-    {
-      m_printer.AddTrailerPrinter (MakeCallback (&PacketMetadataTest::PrintTrailer<N>, this),
-                                   MakeCallback (&PacketMetadataTest::PrintFragment, this));
-      registered = true;
+      ReadItems (current, &item, &extraItem);
+      uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
+      if (uid == 0)
+        {
+          totalSize += 4;
+        }
+      else
+        {
+          totalSize += 4 + ChunkRegistry::GetUidStringFromUid (uid).size ();
+        }
+      totalSize += 1 + 4 + 2 + 4 + 4 + 4;
+      if (current == m_tail)
+        {
+          break;
+        }
+      NS_ASSERT (current != item.next);
+      current = item.next;
     }
-}
-
-
-template <int N>
-void 
-PacketMetadataTest::PrintHeader (std::ostream &os, uint32_t packetUid, uint32_t size, 
-                                const HistoryHeader<N> *header)
-{
-  if (!header->IsOk ())
-    {
-      m_headerError = true;
-    }
-  m_prints.push_back (N);
-}
-
-template <int N>
-void 
-PacketMetadataTest::PrintTrailer (std::ostream &os, uint32_t packetUid, uint32_t size, 
-                                 const HistoryTrailer<N> *trailer)
-{
-  if (!trailer->IsOk ())
-    {
-      m_trailerError = true;
-    }
-  m_prints.push_back (N);
+  return totalSize;
 }
 void 
-PacketMetadataTest::PrintFragment (std::ostream &os,uint32_t packetUid,
-                                  uint32_t size,std::string & name, 
-                                  struct PacketPrinter::FragmentInformation info)
+PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
 {
-  m_prints.push_back (size - (info.end + info.start));
+  uint32_t bytesWritten = 0;
+  i.WriteU32 (size);
+  bytesWritten += 4;
+  struct PacketMetadata::SmallItem item;
+  struct PacketMetadata::ExtraItem extraItem;
+  uint32_t current = m_head;
+  while (current != 0xffff)
+    {
+      ReadItems (current, &item, &extraItem);
+      NS_DEBUG ("bytesWritten=" << bytesWritten << ", typeUid="<<item.typeUid <<
+                ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
+                ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<extraItem.fragmentEnd<<
+                ", packetUid="<<extraItem.packetUid);
+      uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
+      if (uid != 0)
+        {
+          std::string uidString = ChunkRegistry::GetUidStringFromUid (uid);
+          i.WriteU32 (uidString.size ());
+          bytesWritten += 4;
+          i.Write ((uint8_t *)uidString.c_str (), uidString.size ());
+          bytesWritten += uidString.size ();
+        }
+      else
+        {
+          i.WriteU32 (0);
+          bytesWritten += 4;
+        }
+      uint8_t isBig = item.typeUid & 0x1;
+      i.WriteU8 (isBig);
+      bytesWritten += 1;
+      i.WriteU32 (item.size);
+      bytesWritten += 4;
+      i.WriteU16 (item.chunkUid);
+      bytesWritten += 2;
+      i.WriteU32 (extraItem.fragmentStart);
+      bytesWritten += 4;
+      i.WriteU32 (extraItem.fragmentEnd);
+      bytesWritten += 4;
+      i.WriteU32 (extraItem.packetUid);
+      bytesWritten += 4;
+      if (current == m_tail)
+        {
+          break;
+        }
+      
+      NS_ASSERT (current != item.next);
+      current = item.next;
+    }
+  NS_ASSERT (bytesWritten == size);
 }
-void 
-PacketMetadataTest::PrintDefault (std::ostream& os,uint32_t packetUid,
-                     uint32_t size,std::string& name,
-                     struct PacketPrinter::FragmentInformation info)
+uint32_t 
+PacketMetadata::Deserialize (Buffer::Iterator i)
 {
-  NS_ASSERT (false);
-}
-void 
-PacketMetadataTest::PrintPayload (std::ostream &os,uint32_t packetUid,
-                                 uint32_t size,
-                                 struct PacketPrinter::FragmentInformation info)
-{
-  m_prints.push_back (size - (info.end + info.start));
+  struct PacketMetadata::SmallItem item;
+  struct PacketMetadata::ExtraItem extraItem;
+  uint32_t totalSize = i.ReadU32 ();
+  uint32_t size = totalSize;
+  size -= 4;
+  while (size > 0)
+    {
+      uint32_t uidStringSize = i.ReadU32 ();
+      size -= 4;
+      uint32_t uid;
+      if (uidStringSize == 0)
+        {
+          // uid zero for payload.
+          uid = 0;
+        }
+      else
+        {
+          std::string uidString;
+          for (uint32_t j = 0; j < uidStringSize; j++)
+            {
+              uidString.push_back (i.ReadU8 ());
+              size --;
+            }
+          uid = ChunkRegistry::GetUidFromUidString (uidString);
+        }
+      uint8_t isBig = i.ReadU8 ();
+      size --;
+      item.typeUid = (uid << 1) | isBig;
+      item.size = i.ReadU32 ();
+      size -= 4;
+      item.chunkUid = i.ReadU16 ();
+      size -= 2;
+      extraItem.fragmentStart = i.ReadU32 ();
+      size -= 4;
+      extraItem.fragmentEnd = i.ReadU32 ();
+      size -= 4;
+      extraItem.packetUid = i.ReadU32 ();
+      size -= 4;
+      NS_DEBUG ("size=" << size << ", typeUid="<<item.typeUid <<
+                ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
+                ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<extraItem.fragmentEnd<<
+                ", packetUid="<<extraItem.packetUid);
+      uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
+      UpdateTail (tmp);
+    }
+  NS_ASSERT (size == 0);
+  return totalSize;
 }
 
 
-void 
-PacketMetadataTest::CleanupPrints (void)
-{
-  m_prints.clear ();
-}
-
-bool
-PacketMetadataTest::Check (const char *file, int line, std::list<int> expected)
-{
-  if (m_headerError)
-    {
-      std::cout << "PacketMetadata header error. file=" << file 
-                << ", line=" << line << std::endl;
-      return false;
-    }
-  if (m_trailerError)
-    {
-      std::cout << "PacketMetadata trailer error. file=" << file 
-                << ", line=" << line << std::endl;
-      return false;
-    }
-  if (expected.size () != m_prints.size ())
-    {
-      goto error;
-    }
-  for (std::list<int>::iterator i = m_prints.begin (),
-         j = expected.begin (); 
-       i != m_prints.end (); i++, j++)
-    {
-      NS_ASSERT (j != expected.end ());
-      if (*j != *i)
-        {
-          goto error;
-        }
-    }
-  return true;
- error:
-  std::cout << "PacketMetadata error. file="<< file 
-            << ", line=" << line << ", got:\"";
-  for (std::list<int>::iterator i = m_prints.begin (); 
-       i != m_prints.end (); i++)
-    {
-      std::cout << *i << ", ";
-    }
-  std::cout << "\", expected: \"";
-  for (std::list<int>::iterator j = expected.begin ();
-       j != expected.end (); j++)
-    {
-      std::cout << *j << ", ";
-    }
-  std::cout << "\"" << std::endl;
-  return false;
-}
-
-bool 
-PacketMetadataTest::CheckHistory (Packet p, const char *file, int line, uint32_t n, ...)
-{
-  m_headerError = false;
-  m_trailerError = false;
-  std::list<int> expected;
-  va_list ap;
-  va_start (ap, n);
-  for (uint32_t j = 0; j < n; j++)
-    {
-      int v = va_arg (ap, int);
-      expected.push_back (v);
-    }
-  va_end (ap);
-
-  m_printer.PrintForward ();
-  p.Print (std::cerr, m_printer);
-  bool ok = Check (file, line, expected);
-  CleanupPrints ();
-  if (!ok)
-    {
-      return false;
-    }
-
-  m_printer.PrintBackward ();
-  p.Print (std::cerr, m_printer);
-  expected.reverse ();
-  ok = Check (file, line, expected);
-  CleanupPrints ();
-  return ok;
-}
-
-#define ADD_HEADER(p, n)                        \
-  {                                             \
-    HistoryHeader<n> header;                    \
-    RegisterHeader<n> ();                       \
-    p.AddHeader (header);                       \
-  }
-#define ADD_TRAILER(p, n)                       \
-  {                                             \
-    HistoryTrailer<n> trailer;                  \
-    RegisterTrailer<n> ();                      \
-    p.AddTrailer (trailer);                     \
-  }
-#define REM_HEADER(p, n)                        \
-  {                                             \
-    HistoryHeader<n> header;                    \
-    RegisterHeader<n> ();                       \
-    p.RemoveHeader (header);                    \
-  }
-#define REM_TRAILER(p, n)                       \
-  {                                             \
-    HistoryTrailer<n> trailer;                  \
-    RegisterTrailer<n> ();                      \
-    p.RemoveTrailer (trailer);                  \
-  }
-#define CHECK_HISTORY(p, ...)                   \
-  {                                             \
-    if (!CheckHistory (p, __FILE__,             \
-                      __LINE__, __VA_ARGS__))   \
-      {                                         \
-        ok = false;                             \
-      }                                         \
-  }
-
-bool
-PacketMetadataTest::RunTests (void)
-{
-  bool ok = true;
-
-  PacketMetadata::Enable ();
-
-  Packet p = Packet (0);
-  Packet p1 = Packet (0);
-
-  p = Packet (10);
-  ADD_TRAILER (p, 100);
-  CHECK_HISTORY (p, 2, 10, 100);
-
-  p = Packet (10);
-  ADD_HEADER (p, 1);
-  ADD_HEADER (p, 2);
-  ADD_HEADER (p, 3);
-  CHECK_HISTORY (p, 4, 
-                 3, 2, 1, 10);
-  ADD_HEADER (p, 5);
-  CHECK_HISTORY (p, 5, 
-                 5, 3, 2, 1, 10);
-  ADD_HEADER (p, 6);
-  CHECK_HISTORY (p, 6, 
-                 6, 5, 3, 2, 1, 10);
-
-  p = Packet (10);
-  ADD_HEADER (p, 1);
-  ADD_HEADER (p, 2);
-  ADD_HEADER (p, 3);
-  REM_HEADER (p, 3);
-  CHECK_HISTORY (p, 3, 
-                 2, 1, 10);
-
-  p = Packet (10);
-  ADD_HEADER (p, 1);
-  ADD_HEADER (p, 2);
-  ADD_HEADER (p, 3);
-  REM_HEADER (p, 3);
-  REM_HEADER (p, 2);
-  CHECK_HISTORY (p, 2, 
-                 1, 10);
-
-  p = Packet (10);
-  ADD_HEADER (p, 1);
-  ADD_HEADER (p, 2);
-  ADD_HEADER (p, 3);
-  REM_HEADER (p, 3);
-  REM_HEADER (p, 2);
-  REM_HEADER (p, 1);
-  CHECK_HISTORY (p, 1, 10);
+} // namespace ns3
 
-  p = Packet (10);
-  ADD_HEADER (p, 1);
-  ADD_HEADER (p, 2);
-  ADD_HEADER (p, 3);
-  p1 = p;
-  REM_HEADER (p1, 3);
-  REM_HEADER (p1, 2);
-  REM_HEADER (p1, 1);
-  CHECK_HISTORY (p1, 1, 10);
-  CHECK_HISTORY (p, 4, 
-                 3, 2, 1, 10);
-  ADD_HEADER (p1, 1);
-  ADD_HEADER (p1, 2);
-  CHECK_HISTORY (p1, 3, 
-                 2, 1, 10);
-  CHECK_HISTORY (p, 4, 
-                 3, 2, 1, 10);
-  ADD_HEADER (p, 3);
-  CHECK_HISTORY (p, 5, 
-                 3, 3, 2, 1, 10);
-  ADD_TRAILER (p, 4);
-  CHECK_HISTORY (p, 6, 
-                 3, 3, 2, 1, 10, 4);
-  ADD_TRAILER (p, 5);
-  CHECK_HISTORY (p, 7, 
-                 3, 3, 2, 1, 10, 4, 5);
-  REM_HEADER (p, 3);
-  CHECK_HISTORY (p, 6, 
-                 3, 2, 1, 10, 4, 5);
-  REM_TRAILER (p, 5);
-  CHECK_HISTORY (p, 5, 
-                 3, 2, 1, 10, 4);
-  p1 = p;
-  REM_TRAILER (p, 4);
-  CHECK_HISTORY (p, 4, 
-                 3, 2, 1, 10);
-  CHECK_HISTORY (p1, 5, 
-                 3, 2, 1, 10, 4);
-  p1.RemoveAtStart (3);
-  CHECK_HISTORY (p1, 4, 
-                 2, 1, 10, 4);
-  p1.RemoveAtStart (1);
-  CHECK_HISTORY (p1, 4, 
-                 1, 1, 10, 4);
-  p1.RemoveAtStart (1);
-  CHECK_HISTORY (p1, 3, 
-                 1, 10, 4);
-  p1.RemoveAtEnd (4);
-  CHECK_HISTORY (p1, 2, 
-                 1, 10);
-  p1.RemoveAtStart (1);
-  CHECK_HISTORY (p1, 1, 10);
-
-  p = Packet (10);
-  ADD_HEADER (p, 8);
-  ADD_TRAILER (p, 8);
-  ADD_TRAILER (p, 8);
-  p.RemoveAtStart (8+10+8);
-  CHECK_HISTORY (p, 1, 8);
-
-  p = Packet (10);
-  ADD_HEADER (p, 10);
-  ADD_HEADER (p, 8);
-  ADD_TRAILER (p, 6);
-  ADD_TRAILER (p, 7);
-  ADD_TRAILER (p, 9);
-  p.RemoveAtStart (5);
-  p.RemoveAtEnd (12);
-  CHECK_HISTORY (p, 5, 3, 10, 10, 6, 4);
-
-  p = Packet (10);
-  ADD_HEADER (p, 10);
-  ADD_TRAILER (p, 6);
-  p.RemoveAtEnd (18);
-  ADD_TRAILER (p, 5);
-  ADD_HEADER (p, 3);
-  CHECK_HISTORY (p, 3, 3, 8, 5);
-  p.RemoveAtStart (12);
-  CHECK_HISTORY (p, 1, 4);
-  p.RemoveAtEnd (2);
-  CHECK_HISTORY (p, 1, 2);
-  ADD_HEADER (p, 10);
-  CHECK_HISTORY (p, 2, 10, 2);
-  p.RemoveAtEnd (5);
-  CHECK_HISTORY (p, 1, 7);
-
-  Packet p2 = Packet (0);
-  Packet p3 = Packet (0);
-
-  p = Packet (40);
-  ADD_HEADER (p, 5);
-  ADD_HEADER (p, 8);
-  CHECK_HISTORY (p, 3, 8, 5, 40);
-  p1 = p.CreateFragment (0, 5);
-  p2 = p.CreateFragment (5, 5);
-  p3 = p.CreateFragment (10, 43);
-  CHECK_HISTORY (p1, 1, 5);
-  CHECK_HISTORY (p2, 2, 3, 2);
-  CHECK_HISTORY (p3, 2, 3, 40);
-  p1.AddAtEnd (p2);
-  CHECK_HISTORY (p1, 2, 8, 2);
-  CHECK_HISTORY (p2, 2, 3, 2);
-  p1.AddAtEnd (p3);
-  CHECK_HISTORY (p1, 3, 8, 5, 40);
-  CHECK_HISTORY (p2, 2, 3, 2);
-  CHECK_HISTORY (p3, 2, 3, 40);
-  p1 = p.CreateFragment (0, 5);
-  CHECK_HISTORY (p1, 1, 5);
-
-  p3 = Packet (50);
-  ADD_HEADER (p3, 8);
-  CHECK_HISTORY (p3, 2, 8, 50);
-  CHECK_HISTORY (p1, 1, 5);
-  p1.AddAtEnd (p3);
-  CHECK_HISTORY (p1, 3, 5, 8, 50);
-  ADD_HEADER (p1, 5);
-  CHECK_HISTORY (p1, 4, 5, 5, 8, 50);
-  ADD_TRAILER (p1, 2);
-  CHECK_HISTORY (p1, 5, 5, 5, 8, 50, 2);
-  REM_HEADER (p1, 5);
-  CHECK_HISTORY (p1, 4, 5, 8, 50, 2);
-  p1.RemoveAtEnd (60);
-  CHECK_HISTORY (p1, 1, 5);
-  p1.AddAtEnd (p2);
-  CHECK_HISTORY (p1, 2, 8, 2);
-  CHECK_HISTORY (p2, 2, 3, 2);
-
-  p3 = Packet (40);
-  ADD_HEADER (p3, 5);
-  ADD_HEADER (p3, 5);
-  CHECK_HISTORY (p3, 3, 5, 5, 40);
-  p1 = p3.CreateFragment (0, 5);
-  p2 = p3.CreateFragment (5, 5);
-  CHECK_HISTORY (p1, 1, 5);
-  CHECK_HISTORY (p2, 1, 5);
-  p1.AddAtEnd (p2);
-  CHECK_HISTORY (p1, 2, 5, 5);
-
-  p = Packet (0);
-  CHECK_HISTORY (p, 0);
-
-  p3 = Packet (0);
-  ADD_HEADER (p3, 5);
-  ADD_HEADER (p3, 5);
-  CHECK_HISTORY (p3, 2, 5, 5);
-  p1 = p3.CreateFragment (0, 4);
-  p2 = p3.CreateFragment (9, 1);
-  CHECK_HISTORY (p1, 1, 4);
-  CHECK_HISTORY (p2, 1, 1);
-  p1.AddAtEnd (p2);
-  CHECK_HISTORY (p1, 2, 4, 1);
-
-
-  p = Packet (2000);
-  CHECK_HISTORY (p, 1, 2000);
-  
-  p = Packet ();
-  ADD_TRAILER (p, 10);
-  ADD_HEADER (p, 5);
-  p1 = p.CreateFragment (0, 8);
-  p2 = p.CreateFragment (8, 7);
-  p1.AddAtEnd (p2);
-  CHECK_HISTORY (p, 2, 5, 10);
-
-  p = Packet ();
-  ADD_TRAILER (p, 10);
-  REM_TRAILER (p, 10);
-  ADD_TRAILER (p, 10);
-  CHECK_HISTORY (p, 1, 10);
-
-  p = Packet ();
-  ADD_HEADER (p, 10);
-  REM_HEADER (p, 10);
-  ADD_HEADER (p, 10);
-  CHECK_HISTORY (p, 1, 10);
-
-  return ok;
-}
-
-static PacketMetadataTest g_packetHistoryTest;
-
-}//namespace ns3
--- a/src/common/packet-metadata.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet-metadata.h	Wed Sep 05 18:35:39 2007 +0100
@@ -100,9 +100,12 @@
 
   uint32_t GetUid (void) const;
 
-  void PrintDefault (std::ostream &os, Buffer buffer) const;
   void Print (std::ostream &os, Buffer buffer, PacketPrinter const &printer) const;
 
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator i, uint32_t size) const;
+  uint32_t Deserialize (Buffer::Iterator i);
+
   static void PrintStats (void);
 
 private:
@@ -254,26 +257,26 @@
 void 
 PacketMetadata::AddHeader (T const &header, uint32_t size)
 {
-  DoAddHeader (PacketPrinter::GetHeaderUid<T> (), size);
+  DoAddHeader (T::GetUid () << 1, size);
 }
 
 template <typename T>
 void 
 PacketMetadata::RemoveHeader (T const &header, uint32_t size)
 {
-  DoRemoveHeader (PacketPrinter::GetHeaderUid<T> (), size);
+  DoRemoveHeader (T::GetUid () << 1, size);
 }
 template <typename T>
 void 
 PacketMetadata::AddTrailer (T const &trailer, uint32_t size)
 {
-  DoAddTrailer (PacketPrinter::GetTrailerUid<T> (), size);
+  DoAddTrailer (T::GetUid () << 1, size);
 }
 template <typename T>
 void 
 PacketMetadata::RemoveTrailer (T const &trailer, uint32_t size)
 {
-  DoRemoveTrailer (PacketPrinter::GetTrailerUid<T> (), size);
+  DoRemoveTrailer (T::GetUid () << 1, size);
 }
 
 
@@ -303,24 +306,23 @@
 PacketMetadata &
 PacketMetadata::operator = (PacketMetadata const& o)
 {
-  if (m_data == o.m_data) 
+  if (m_data != o.m_data) 
     {
-      // self assignment
-      return *this;
+      // not self assignment
+      NS_ASSERT (m_data != 0);
+      m_data->m_count--;
+      if (m_data->m_count == 0) 
+        {
+          PacketMetadata::Recycle (m_data);
+        }
+      m_data = o.m_data;
+      NS_ASSERT (m_data != 0);
+      m_data->m_count++;
     }
-  NS_ASSERT (m_data != 0);
-  m_data->m_count--;
-  if (m_data->m_count == 0) 
-    {
-      PacketMetadata::Recycle (m_data);
-    }
-  m_data = o.m_data;
   m_head = o.m_head;
   m_tail = o.m_tail;
   m_used = o.m_used;
   m_packetUid = o.m_packetUid;
-  NS_ASSERT (m_data != 0);
-  m_data->m_count++;
   return *this;
 }
 PacketMetadata::~PacketMetadata ()
--- a/src/common/packet-printer.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet-printer.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -20,12 +20,13 @@
  */
 
 #include "packet-printer.h"
+#include "chunk-registry.h"
 
 namespace ns3 {
 
 PacketPrinter::PacketPrinter ()
   : m_forward (true),
-    m_separator ("")
+    m_separator (" ")
 {}
 
 void 
@@ -44,44 +45,10 @@
   m_separator = separator;
 }
 void 
-PacketPrinter::AddPayloadPrinter (PayloadPrinter printer)
+PacketPrinter::SetPayloadPrinter (PayloadPrinter printer)
 {
   m_payloadPrinter = printer;
 }
-void 
-PacketPrinter::AddDefaultPrinter (DefaultPrinter printer)
-{
-  m_defaultPrinter = printer;
-}
-
-PacketPrinter::RegisteredChunks *
-PacketPrinter::GetRegisteredChunks (void)
-{
-  static RegisteredChunks registeredChunks;
-  return &registeredChunks;
-}
-
-PacketPrinter 
-PacketPrinter::GetDefault (void)
-{
-  return *(PacketPrinter::PeekDefault ());
-}
-PacketPrinter *
-PacketPrinter::PeekDefault (void)
-{
-  static PacketPrinter *tmp = PacketPrinter::CreateStaticDefault ();
-  return tmp;
-}
-PacketPrinter *
-PacketPrinter::CreateStaticDefault (void)
-{
-  static PacketPrinter tmp;
-  tmp.PrintForward ();
-  tmp.AddPayloadPrinter (MakeCallback (&PacketPrinter::DoDefaultPrintPayload));
-  tmp.SetSeparator (" ");
-  return &tmp;
-}
-
 
 void 
 PacketPrinter::PrintChunk (uint32_t chunkUid, 
@@ -90,26 +57,22 @@
                            uint32_t packetUid,
                            uint32_t size) const
 {
-  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
-  NS_ASSERT (chunkUid >= 1 && chunkUid/2 <= registeredChunks->size ());
+  uint8_t *instance = ChunkRegistry::GetStaticInstance (chunkUid);
+  ChunkRegistry::Deserialize (chunkUid, instance, start);
+
   for (PrinterList::const_iterator i = m_printerList.begin (); i != m_printerList.end (); i++)
     {
       if (i->m_chunkUid == chunkUid)
         {
-          DoPrintCallback cb = (*registeredChunks)[chunkUid/2-1].printCallback;
-          cb (i->m_printer, start, os, packetUid, size);
+          ChunkRegistry::InvokePrintCallback (chunkUid, instance, os, packetUid, size, i->m_printer);
           return;
         }
     }
-  DoGetNameCallback cb = (*registeredChunks)[chunkUid/2-1].getNameCallback;
-  std::string name = cb ();
-  struct PacketPrinter::FragmentInformation info;
-  info.start = 0;
-  info.end = 0;
-  if (!m_defaultPrinter.IsNull ())
-    {
-      m_defaultPrinter (os, packetUid, size, name, info);
-    }
+  // if the over did not override this type of chunk,
+  // we print something by default.
+  std::string name = ChunkRegistry::GetName (chunkUid, instance);
+  os << name;
+  ChunkRegistry::Print (chunkUid, instance, os);
 }
 void 
 PacketPrinter::PrintChunkFragment (uint32_t chunkUid,
@@ -119,10 +82,8 @@
                                    uint32_t fragmentStart,
                                    uint32_t fragmentEnd) const
 {
-  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
-  NS_ASSERT (chunkUid >= 1 && chunkUid/2 <= registeredChunks->size ());
-  DoGetNameCallback cb = (*registeredChunks)[chunkUid/2-1].getNameCallback;
-  std::string name = cb ();
+  uint8_t *instance = ChunkRegistry::GetStaticInstance (chunkUid);
+  std::string name = ChunkRegistry::GetName (chunkUid, instance);
   struct PacketPrinter::FragmentInformation info;
   info.start = fragmentStart;
   info.end = fragmentEnd;
@@ -130,14 +91,20 @@
     {
       if (i->m_chunkUid == chunkUid)
         {
+
           i->m_fragmentPrinter (os, packetUid, size, name, info);
           return;
         }
     }
-  if (!m_defaultPrinter.IsNull ())
-    {
-      m_defaultPrinter (os, packetUid, size, name, info);
-    }
+  // if the user did not override this type of chunk,
+  // we print something by default.
+  NS_ASSERT (info.start != 0 || info.end != 0);
+  os << name << " "
+     << "("
+     << "length " << size - (info.end + info.start) << " "
+     << "trim_start " << info.start << " "
+     << "trim_end " << info.end
+     << ")";
 }
 void 
 PacketPrinter::PrintPayload (std::ostream &os, uint32_t packetUid, uint32_t size,
@@ -149,15 +116,10 @@
   if (!m_payloadPrinter.IsNull ())
     {
       m_payloadPrinter (os, packetUid, size, info);
+      return;
     }
-}
-
-void 
-PacketPrinter::DoDefaultPrintPayload (std::ostream & os,
-                                      uint32_t packetUid,
-                                      uint32_t size,
-                                      struct PacketPrinter::FragmentInformation info)
-{
+  // if the user did not override the payload printer,
+  // we print something anyway.
   os << "DATA ("
      << "length " << size - (info.end + info.start);
   if (info.start != 0 || info.end != 0)
@@ -167,69 +129,7 @@
          << "trim_end " << info.end;
     }
   os << ")";
-}
 
-void 
-PacketPrinter::DoDefaultPrintDefault (std::ostream & os,
-                                      uint32_t packetUid,
-                                      uint32_t size,
-                                      std::string &name,
-                                      struct PacketPrinter::FragmentInformation info)
-{
-  NS_ASSERT_MSG (false, "This should never happen because we provide a printer for _all_ chunk types.");
-}
-
-void 
-PacketPrinter::DoDefaultPrintFragment (std::ostream & os,
-                                       uint32_t packetUid,
-                                       uint32_t size,
-                                       std::string &name,
-                                       struct PacketPrinter::FragmentInformation info)
-{
-  NS_ASSERT (info.start != 0 || info.end != 0);
-  os << name << " "
-     << "("
-     << "length " << size - (info.end + info.start) << " "
-     << "trim_start " << info.start << " "
-     << "trim_end " << info.end
-     << ")"
-    ;
 }
 
-void
-PacketPrinter::DoAddPrinter (uint32_t uid,
-                             Ptr<CallbackImplBase> printer,
-                             Callback<void,
-                             std::ostream &, 
-                             uint32_t, 
-                             uint32_t, 
-                             std::string &,
-                             struct PacketPrinter::FragmentInformation> fragmentPrinter)
-{
-  struct PacketPrinter::Printer p;
-  p.m_chunkUid = uid;
-  p.m_printer = printer;
-  p.m_fragmentPrinter = fragmentPrinter;
-  m_printerList.push_back (p);
-}
-
-bool 
-PacketPrinter::IsTrailer (uint32_t uid)
-{
-  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
-  NS_ASSERT (uid >= 1 && uid/2 <= registeredChunks->size ());
-  bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
-  return !isHeader;
-}
-bool 
-PacketPrinter::IsHeader (uint32_t uid)
-{
-  RegisteredChunks *registeredChunks = PacketPrinter::GetRegisteredChunks ();
-  NS_ASSERT (uid >= 1 && uid/2 <= registeredChunks->size ());
-  bool isHeader = (*registeredChunks)[uid/2-1].isHeader;
-  return isHeader;
-}
-
-
-
 } // namespace ns3
--- a/src/common/packet-printer.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet-printer.h	Wed Sep 05 18:35:39 2007 +0100
@@ -26,14 +26,8 @@
 #include "buffer.h"
 #include <vector>
 
-namespace {
-  class ItemList;
-}
-
 namespace ns3 {
 
-class Chunk;
-
 /**
  * \brief hold a list of print callbacks for packet headers and trailers
  *
@@ -92,99 +86,38 @@
    * Print the content of the packet backward.
    */
   void PrintBackward (void);
+  /**
+   * \param separator the new separator
+   *
+   * The default separator is a single space character.
+   */
   void SetSeparator (std::string separator);
   /**
    * \param printer printer for payload
    */
-  void AddPayloadPrinter (PayloadPrinter printer);
+  void SetPayloadPrinter (PayloadPrinter printer);
   /**
    * \param printer printer for the specified chunk
    * \param fragmentPrinter printer for a fragment of the specified chunk
    *
-   * If the user has not specified a callback for a specific header present
-   * in a packet, the "default" callback is invoked. If no such callback
-   * was specified, nothing happens.
+   * If the user does not force a user-specific printing function through
+   * a call to SetHeaderPrinter, the default print output is generated.
    */
   template <typename T>
-  void AddHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+  void SetHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
                          ChunkFragmentPrinter fragmentPrinter);
   /**
    * \param printer printer for the specified chunk
    * \param fragmentPrinter printer for a fragment of the specified chunk
    *
-   * If the user has not specified a callback for a specific trailer present
-   * in a packet, the "default" callback is invoked. If no such callback
-   * was specified, nothing happens.
+   * If the user does not force a user-specific printing function through
+   * a call to SetTrailerPrinter, the default print output is generated.
    */
   template <typename T>
-  void AddTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
-                          ChunkFragmentPrinter fragmentPrinter);
-  /**
-   * \param printer printer for a chunk for which no callback was specified explicitely
-   */
-  void AddDefaultPrinter (DefaultPrinter printer);
-  
+  void SetTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+                          ChunkFragmentPrinter fragmentPrinter);  
 private:
   friend class PacketMetadata;
-  typedef void (*DoPrintCallback) (Ptr<CallbackImplBase>, Buffer::Iterator, std::ostream &,
-                                   uint32_t, uint32_t);
-  typedef std::string (*DoGetNameCallback) (void);
-  struct Printer
-  {
-    uint32_t m_chunkUid;
-    Ptr<CallbackImplBase> m_printer;
-    Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,struct PacketPrinter::FragmentInformation>
-      m_fragmentPrinter;
-  };
-  struct RegisteredChunk
-  {
-    DoPrintCallback printCallback;
-    DoGetNameCallback getNameCallback;
-    bool isHeader;
-  };
-  typedef std::vector<struct PacketPrinter::Printer> PrinterList;
-  typedef std::vector<struct RegisteredChunk> RegisteredChunks;
-
-
-  static PacketPrinter GetDefault (void);
-  static PacketPrinter *PeekDefault (void);
-  static PacketPrinter *CreateStaticDefault (void);
-  static void DoDefaultPrintPayload (std::ostream & os,
-                                     uint32_t packetUid,
-                                     uint32_t size,
-                                     struct PacketPrinter::FragmentInformation info);
-  static void DoDefaultPrintDefault (std::ostream & os,
-                                     uint32_t packetUid,
-                                     uint32_t size,
-                                     std::string &name,
-                                     struct PacketPrinter::FragmentInformation info);
-  template <typename T>
-  static void DoDefaultPrint (std::ostream &os, uint32_t packetUid, uint32_t size, const T *chunk);
-  static void DoDefaultPrintFragment (std::ostream & os,
-                                      uint32_t packetUid,
-                                      uint32_t size,
-                                      std::string &name,
-                                      struct PacketPrinter::FragmentInformation info);
-
-  template <typename T>
-  static void DoPrint (Ptr<CallbackImplBase> callbackPrinter,
-                       Buffer::Iterator i, 
-                       std::ostream &os, 
-                       uint32_t packetUid,
-                       uint32_t size);
-  template <typename T>
-  static std::string DoGetName (void);
-  template <typename T>
-  static uint32_t GetTrailerUid (void);
-  template <typename T>
-  static uint32_t GetHeaderUid (void);
-  template <typename T>
-  static uint32_t AllocateUid (bool isHeader);
-  static RegisteredChunks *GetRegisteredChunks (void);
-  static bool IsTrailer (uint32_t uid);
-  static bool IsHeader (uint32_t uid);
-
-
   void PrintChunk (uint32_t uid, 
 		   Buffer::Iterator i, 
 		   std::ostream &os, 
@@ -198,16 +131,15 @@
 			   uint32_t fragmentEnd) const;
   void PrintPayload (std::ostream &os, uint32_t packetUid, uint32_t size,
 		     uint32_t fragmentStart, uint32_t fragmentEnd) const;
-  void DoAddPrinter (uint32_t uid,
-                     Ptr<CallbackImplBase> printer,
-                     Callback<void,
-                       std::ostream &, 
-                       uint32_t, 
-                       uint32_t, 
-                       std::string &,
-                       struct PacketPrinter::FragmentInformation> fragmentPrinter);
-
-  static PacketPrinter m_defaultPacketPrinter;
+  struct Printer
+  {
+    uint32_t m_chunkUid;
+    Ptr<CallbackImplBase> m_printer;
+    Callback<void,std::ostream &,uint32_t,uint32_t,std::string &,
+             struct PacketPrinter::FragmentInformation> m_fragmentPrinter;
+  };
+  typedef std::vector<struct PacketPrinter::Printer> PrinterList;
+  
   PrinterList m_printerList;
   PayloadPrinter m_payloadPrinter;
   DefaultPrinter m_defaultPrinter;
@@ -221,97 +153,28 @@
 
 template <typename T>
 void 
-PacketPrinter::AddHeaderPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
-			   Callback<void,
-		            std::ostream &, 
-		            uint32_t, 
-                            uint32_t, 
-                            std::string &,
-		            struct PacketPrinter::FragmentInformation> fragmentPrinter)
+PacketPrinter::SetHeaderPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+                                 ChunkFragmentPrinter fragmentPrinter)
 {
-  static uint32_t uid = PacketPrinter::GetHeaderUid<T> ();
-  DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
+  Printer p;
+  p.m_chunkUid = T::GetUid ();
+  p.m_printer = printer.GetImpl ();
+  p.m_fragmentPrinter = fragmentPrinter;
+  m_printerList.push_back (p);
 }
 
 template <typename T>
 void 
-PacketPrinter::AddTrailerPrinter (Callback<void,std::ostream &, uint32_t, uint32_t, const T *> printer,
-			   Callback<void,
-		            std::ostream &, 
-		            uint32_t, 
-                            uint32_t, 
-                            std::string &,
-		            struct PacketPrinter::FragmentInformation> fragmentPrinter)
+PacketPrinter::SetTrailerPrinter (Callback<void,std::ostream &,uint32_t,uint32_t,const T *> printer,
+                                 ChunkFragmentPrinter fragmentPrinter)
 {
-  static uint32_t uid = PacketPrinter::GetTrailerUid<T> ();
-  DoAddPrinter (uid, printer.GetImpl (), fragmentPrinter);
-}
-
-template <typename T>
-void
-PacketPrinter::DoPrint (Ptr<CallbackImplBase> printerCallback,
-                        Buffer::Iterator i,
-                        std::ostream &os, 
-                        uint32_t packetUid,
-                        uint32_t size)
-{
-  T chunk = T ();
-  chunk.Deserialize (i);
-  Callback<void,std::ostream&,uint32_t,uint32_t,const T*> callback;
-  callback.Assign (printerCallback);
-  callback (os, packetUid, size, &chunk);
-}
-
-template <typename T>
-std::string
-PacketPrinter::DoGetName (void)
-{
-  T chunk = T ();
-  return chunk.GetName ();
+  Printer p;
+  p.m_chunkUid = T::GetUid ();
+  p.m_printer = printer.GetImpl ();
+  p.m_fragmentPrinter = fragmentPrinter;
+  m_printerList.push_back (p);
 }
 
-template <typename T>
-uint32_t 
-PacketPrinter::GetHeaderUid (void)
-{
-  static uint32_t uid = PacketPrinter::AllocateUid<T> (true);
-  return uid;
-}
-
-template <typename T>
-uint32_t 
-PacketPrinter::GetTrailerUid (void)
-{
-  static uint32_t uid = PacketPrinter::AllocateUid<T> (false);
-  return uid;
-}
-
-template <typename T>
-uint32_t
-PacketPrinter::AllocateUid (bool isHeader)
-{
-  RegisteredChunks *chunks = PacketPrinter::GetRegisteredChunks ();
-  RegisteredChunk chunk;
-  chunk.printCallback = &PacketPrinter::DoPrint<T>;
-  chunk.getNameCallback = &PacketPrinter::DoGetName<T>;
-  chunk.isHeader = isHeader;
-  chunks->push_back (chunk);
-  uint32_t uid = chunks->size () * 2;
-  PacketPrinter::PeekDefault ()->DoAddPrinter (uid, 
-                                               MakeCallback (&PacketPrinter::DoDefaultPrint<T>).GetImpl (),
-                                               MakeCallback (&PacketPrinter::DoDefaultPrintFragment));
-  return uid;
-}
-
-template <typename T>
-void 
-PacketPrinter::DoDefaultPrint (std::ostream &os, uint32_t packetUid, uint32_t size, const T *chunk)
-{
-  os << chunk->GetName () << " ";
-  chunk->Print (os);
-}
-
-
 
 } // namespace ns3
 
--- a/src/common/packet.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -74,14 +74,14 @@
 void 
 Packet::AddAtEnd (Packet packet)
 {
-  packet.m_buffer.TransformIntoRealBuffer ();
-  m_buffer.TransformIntoRealBuffer ();
+  Buffer src = packet.m_buffer.CreateFullCopy ();
+  Buffer dst = m_buffer.CreateFullCopy ();
 
-  Buffer src = packet.m_buffer;
-  m_buffer.AddAtEnd (src.GetSize ());
-  Buffer::Iterator destStart = m_buffer.End ();
+  dst.AddAtEnd (src.GetSize ());
+  Buffer::Iterator destStart = dst.End ();
   destStart.Prev (src.GetSize ());
   destStart.Write (src.Begin (), src.End ());
+  m_buffer = dst;
   /**
    * XXX: we might need to merge the tag list of the
    * other packet into the current packet.
@@ -126,9 +126,15 @@
 }
 
 void 
+Packet::PrintTags (std::ostream &os) const
+{
+  m_tags.Print (os, " ");
+}
+
+void 
 Packet::Print (std::ostream &os) const
 {
-  m_metadata.PrintDefault (os, m_buffer);
+  m_metadata.Print (os, m_buffer, PacketPrinter ());
 }
 
 void 
@@ -143,7 +149,58 @@
   PacketMetadata::Enable ();
 }
 
-}; // namespace ns3
+Buffer 
+Packet::Serialize (void) const
+{
+  Buffer buffer;
+  uint32_t reserve;
+
+  // write metadata
+  reserve = m_metadata.GetSerializedSize ();
+  buffer.AddAtStart (reserve);
+  m_metadata.Serialize (buffer.Begin (), reserve);
+
+  // write tags
+  reserve = m_tags.GetSerializedSize ();
+  buffer.AddAtStart (reserve);
+  m_tags.Serialize (buffer.Begin (), reserve);
+  
+  // aggregate byte buffer, metadata, and tags
+  Buffer tmp = m_buffer.CreateFullCopy ();
+  buffer.AddAtStart (tmp.GetSize ());
+  buffer.Begin ().Write (tmp.Begin (), tmp.End ());
+  
+  // write byte buffer size.
+  buffer.AddAtStart (4);
+  buffer.Begin ().WriteU32 (m_buffer.GetSize ());
+
+  return buffer;
+}
+void 
+Packet::Deserialize (Buffer buffer)
+{
+  Buffer buf = buffer;
+  // read size
+  uint32_t packetSize = buf.Begin ().ReadU32 ();
+  buf.RemoveAtStart (4);
+
+  // read buffer.
+  buf.RemoveAtEnd (buf.GetSize () - packetSize);
+  m_buffer = buf;
+
+  // read tags
+  buffer.RemoveAtStart (4 + packetSize);
+  uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
+  buffer.RemoveAtStart (tagsDeserialized);
+
+  // read metadata
+  uint32_t metadataDeserialized = 
+    m_metadata.Deserialize (buffer.Begin ());
+  buffer.RemoveAtStart (metadataDeserialized);
+}
+
+
+} // namespace ns3
 
 
 
--- a/src/common/packet.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/packet.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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"
 
@@ -37,12 +38,15 @@
 /**
  * \brief network packets
  *
- * Each network packet contains a byte buffer and a list of tags.
+ * Each network packet contains a byte buffer, a list of tags, and
+ * metadata.
+ *
  * - The byte buffer stores the serialized content of the headers and trailers 
  * added to a packet. The serialized representation of these headers is expected
  * to match that of real network packets bit for bit (although nothing
  * forces you to do this) which means that the content of a packet buffer
  * is expected to be that of a real packet.
+ *
  * - The list of tags stores an arbitrarily large set of arbitrary 
  * user-provided data structures in the packet: only one instance of
  * each type of data structure is allowed in a list of tags. 
@@ -51,43 +55,22 @@
  * 16 bytes big. Trying to attach bigger data structures will trigger
  * crashes at runtime.
  *
- * Implementing a new type of Header for a new protocol is pretty easy
- * and is a matter of creating a subclass of the ns3::Header base class,
- * and implementing the 4 pure virtual methods defined in ns3::Header.
- * Sample code which shows how to create such a new Header, how to use
- * it, and how to manipulate tags is shown below:
- * \include samples/main-packet.cc
- *
- * 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 
- * Meyer's "More Effective C++", items 17 and 29). What this means is that
- * copying packets without modifying them is very cheap (in terms of cpu
- * and memory usage) and modifying them can be also very cheap. What is 
- * key for proper COW implementations is being
- * able to detect when a given modification of the state of a packet triggers
- * a full copy of the data prior to the modification: COW systems need
- * to detect when an operation is "dirty".
+ * - The metadata describes the type of the headers and trailers which
+ * were serialized in the byte buffer. The maintenance of metadata is
+ * optional and disabled by default. To enable it, you must call
+ * Packet::EnableMetadata and this will allow you to get non-empty
+ * output from Packet::Print and Packet::Print.
  *
- * Dirty operations:
- *   - ns3::Packet::RemoveTag
- *   - ns3::Packet::Add
- *   - both versions of ns3::Packet::AddAtEnd
+ * 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 methods
+ * described in their respective API documentation.
  *
- * Non-dirty operations:
- *   - ns3::Packet::AddTag
- *   - ns3::Packet::RemoveAllTags
- *   - ns3::Packet::PeekTag
- *   - ns3::Packet::Peek
- *   - ns3::Packet::Remove
- *   - ns3::Packet::CreateFragment
- *   - ns3::Packet::RemoveAtStart
- *   - ns3::Packet::RemoveAtEnd
+ * Implementing a new type of Tag requires roughly the same amount of
+ * work and this work is described in the ns3::Tag API documentation.
  *
- * Dirty operations will always be slower than non-dirty operations,
- * sometimes by several orders of magnitude. However, even the
- * dirty operations have been optimized for common use-cases which
- * means that most of the time, these operations will not trigger
- * data copies and will thus be still very fast.
+ * The performance aspects of the Packet API are discussed in 
+ * \ref packetperf
  */
 class Packet {
 public:
@@ -132,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.
    *
@@ -142,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.
@@ -151,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.
    *
@@ -161,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.
@@ -171,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.
    */
@@ -198,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
@@ -211,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.
    *
@@ -294,6 +288,38 @@
    * errors will be detected and will abort the program.
    */
   static void EnableMetadata (void);
+
+  /**
+   * \returns a byte buffer
+   *
+   * This method creates a serialized representation of a Packet object
+   * ready to be transmitted over a network to another system. This
+   * 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 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 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.
+   */
+  void Deserialize (Buffer buffer);
 private:
   Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
   Buffer m_buffer;
@@ -302,7 +328,42 @@
   static uint32_t m_globalUid;
 };
 
-}; // namespace ns3
+/**
+ * \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 
+ * Meyer's "More Effective C++", items 17 and 29). What this means is that
+ * copying packets without modifying them is very cheap (in terms of cpu
+ * and memory usage) and modifying them can be also very cheap. What is 
+ * key for proper COW implementations is being
+ * able to detect when a given modification of the state of a packet triggers
+ * a full copy of the data prior to the modification: COW systems need
+ * to detect when an operation is "dirty".
+ *
+ * Dirty operations:
+ *   - ns3::Packet::RemoveTag
+ *   - ns3::Packet::AddHeader
+ *   - ns3::Packet::AddTrailer
+ *   - both versions of ns3::Packet::AddAtEnd
+ *
+ * Non-dirty operations:
+ *   - ns3::Packet::AddTag
+ *   - ns3::Packet::RemoveAllTags
+ *   - ns3::Packet::PeekTag
+ *   - ns3::Packet::RemoveHeader
+ *   - ns3::Packet::RemoveTrailer
+ *   - ns3::Packet::CreateFragment
+ *   - ns3::Packet::RemoveAtStart
+ *   - ns3::Packet::RemoveAtEnd
+ *
+ * Dirty operations will always be slower than non-dirty operations,
+ * sometimes by several orders of magnitude. However, even the
+ * dirty operations have been optimized for common use-cases which
+ * means that most of the time, these operations will not trigger
+ * data copies and will thus be still very fast.
+ */
+
+} // namespace ns3
 
 
 /**************************************************
@@ -316,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);
@@ -327,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);
@@ -338,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);
@@ -350,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);
@@ -362,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	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/tags.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -20,84 +20,10 @@
  */
 #include "tags.h"
 #include <string.h>
+#include "ns3/fatal-error.h"
 
 namespace ns3 {
 
-TagRegistry *
-TagRegistry::GetInstance (void)
-{
-  static TagRegistry registry;
-  return &registry;
-}
-
-TagRegistry::TagRegistry ()
-  : m_sorted (false)
-{}
-
-
-void 
-TagRegistry::Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor)
-{
-  NS_ASSERT (!m_sorted);
-  struct TagInfoItem item;
-  item.uuid = uuid;
-  item.printer = prettyPrinter;
-  item.destructor = destructor;
-  m_registry.push_back (item);
-}
-bool 
-TagRegistry::CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b)
-{
-  return a.uuid < b.uuid;
-}
-uint32_t 
-TagRegistry::LookupUid (std::string uuid)
-{
-  if (!m_sorted) 
-    {
-      std::sort (m_registry.begin (), m_registry.end (), &TagRegistry::CompareItem);
-      m_sorted = true;
-    }
-  NS_ASSERT (m_sorted);
-  uint32_t uid = 1;
-  for (TagsDataCI i = m_registry.begin (); i != m_registry.end (); i++) 
-    {
-      if (i->uuid == uuid) 
-        {
-          return uid;
-        }
-      uid++;
-    }
-  // someone asked for a uid for an unregistered uuid.
-  NS_ASSERT (!"You tried to use unregistered tag: make sure you create an instance of type TagRegistration<YouTagType>.");
-  // quiet compiler
-  return 0;
-}
-void 
-TagRegistry::PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
-{
-  NS_ASSERT (uid > 0);
-  uint32_t index = uid - 1;
-  NS_ASSERT (m_registry.size () > index);
-  PrettyPrinter prettyPrinter = m_registry[index].printer;
-  if (prettyPrinter != 0) 
-    {
-      prettyPrinter (buf, os);
-    }
-}
-void 
-TagRegistry::Destruct (uint32_t uid, uint8_t buf[Tags::SIZE])
-{
-  NS_ASSERT (uid > 0);
-  uint32_t index = uid - 1;
-  NS_ASSERT (m_registry.size () > index);
-  Destructor destructor = m_registry[index].destructor;
-  NS_ASSERT (destructor != 0);
-  destructor (buf);
-}
-
-
-
 #ifdef USE_FREE_LIST
 
 struct Tags::TagData *Tags::gFree = 0;
@@ -193,13 +119,102 @@
 }
 
 void 
-Tags::PrettyPrint (std::ostream &os)
+Tags::Print (std::ostream &os, std::string separator) const
 {
   for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
     {
-      TagRegistry::GetInstance ()->PrettyPrint (cur->m_id, cur->m_data, os);
+      TagRegistry::Print (cur->m_id, cur->m_data, os);
+      if (cur->m_next != 0)
+        {
+          os << separator;
+        }
+    }
+}
+
+uint32_t
+Tags::GetSerializedSize (void) const
+{
+  uint32_t totalSize = 4; // reserve space for the size of the tag data.
+  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
+    {
+      uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
+      if (size != 0)
+        {
+          std::string uidString = TagRegistry::GetUidString (cur->m_id);
+          totalSize += 4; // for the size of the string itself.
+          totalSize += uidString.size ();
+          totalSize += size;
+        }
+    }
+  return totalSize;
+}
+
+void 
+Tags::Serialize (Buffer::Iterator i, uint32_t totalSize) const
+{
+  i.WriteU32 (totalSize);
+  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
+    {
+      uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
+      if (size != 0)
+        {
+          std::string uidString = TagRegistry::GetUidString (cur->m_id);
+          i.WriteU32 (uidString.size ());
+          uint8_t *buf = (uint8_t *)uidString.c_str ();
+          i.Write (buf, uidString.size ());
+          TagRegistry::Serialize (cur->m_id, cur->m_data, i);
+        }
     }
 }
+uint32_t
+Tags::Deserialize (Buffer::Iterator i)
+{
+  uint32_t totalSize = i.ReadU32 ();
+  uint32_t bytesRead = 4;
+  while (bytesRead < totalSize)
+    {
+      uint32_t uidStringSize = i.ReadU32 ();
+      bytesRead += 4;
+      std::string uidString;
+      uidString.reserve (uidStringSize);
+      for (uint32_t j = 0; j < uidStringSize; j++)
+        {
+          uint32_t c = i.ReadU8 ();
+          uidString.push_back (c);
+        }
+      bytesRead += uidStringSize;
+      uint32_t uid = TagRegistry::GetUidFromUidString (uidString);
+      struct TagData *newStart = AllocData ();
+      newStart->m_count = 1;
+      newStart->m_next = 0;
+      newStart->m_id = uid;
+      bytesRead += TagRegistry::Deserialize (uid, newStart->m_data, i);
+      newStart->m_next = m_next;
+      m_next = newStart;
+    }
+  NS_ASSERT (bytesRead == totalSize);
+  /**
+   * The process of serialization/deserialization 
+   * results in an inverted linked-list after
+   * deserialization so, we invert the linked-list
+   * in-place here.
+   * Note: the algorithm below is pretty classic
+   * but whenever I get to code it, it makes my
+   * brain hurt :)
+   */
+  struct TagData *prev = 0;
+  struct TagData *cur = m_next;
+  while (cur != 0)
+    {
+      struct TagData *next = cur->m_next;
+      cur->m_next = prev;
+      prev = cur;
+      cur = next;
+    }
+  m_next = prev;
+  return totalSize;
+}
+
 
 
 }; // namespace ns3
@@ -224,25 +239,67 @@
   virtual bool RunTests (void);
 };
 
-struct myTagA {
+class myTagA : public Tag
+{
+public:
+  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);}
+  uint32_t Deserialize (Buffer::Iterator i) {a = i.ReadU8 (); return 1;}
+
   uint8_t a;
 };
-struct myTagB {
+class myTagB : public Tag
+{
+public:
+  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);}
+  uint32_t Deserialize (Buffer::Iterator i) {b = i.ReadU32 (); return 4;}
+
   uint32_t b;
 };
-struct myTagC {
+class myTagC : public Tag
+{
+public:
+  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];
 };
-struct myInvalidTag {
+class myInvalidTag : public Tag
+{
+public:
+  static uint32_t GetUid (void) 
+  {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 {}
+  uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
   uint8_t invalid [Tags::SIZE+1];
 };
-struct myTagZ {
+class myTagZ  : public Tag
+{
+public:
+  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 {}
+  uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
   uint8_t z;
 };
 
-class MySmartTag 
+class MySmartTag : public Tag
 {
 public:
+  static uint32_t GetUid (void) 
+  {static uint32_t uid = AllocateUid<MySmartTag> ("MySmartTag.test.nsnam.org"); return uid;}
   MySmartTag ()
   {
     //std::cout << "construct" << std::endl;
@@ -260,43 +317,12 @@
     //std::cout << "assign" << std::endl;
     return *this;
   }
-  static void PrettyPrinterCb (const MySmartTag *a, std::ostream &os)
-  {}
+  void Print (std::ostream &os) const {}
+  uint32_t GetSerializedSize (void) const {return 0;}
+  void Serialize (Buffer::Iterator i) const {}
+  uint32_t Deserialize (Buffer::Iterator i) {return 0;}
 };
 
-static void 
-myTagAPrettyPrinterCb (struct myTagA const*a, std::ostream &os)
-{
-  //os << "struct myTagA, a="<<(uint32_t)a->a<<std::endl;
-  g_a = true;
-}
-static void 
-myTagBPrettyPrinterCb (struct myTagB const*b, std::ostream &os)
-{
-  //os << "struct myTagB, b="<<b->b<<std::endl;
-  g_b = true;
-}
-static void 
-myTagCPrettyPrinterCb (struct myTagC const*c, std::ostream &os)
-{
-  //os << "struct myTagC, c="<<(uint32_t)c->c[0]<<std::endl;
-  g_c = true;
-}
-static void 
-myTagZPrettyPrinterCb (struct myTagZ const*z, std::ostream &os)
-{
-  //os << "struct myTagZ" << std::endl;
-  g_z = true;
-}
-
-
-static TagRegistration<struct myTagA> gMyTagARegistration ("A", &myTagAPrettyPrinterCb);
-static TagRegistration<struct myTagB> gMyTagBRegistration ("B", &myTagBPrettyPrinterCb);
-static TagRegistration<struct myTagC> gMyTagCRegistration ("C", &myTagCPrettyPrinterCb);
-static TagRegistration<struct myTagZ> g_myTagZRegistration ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", 
-                                                            &myTagZPrettyPrinterCb);
-static TagRegistration<MySmartTag> g_myTagSmartRegistration ("SmartTag", &MySmartTag::PrettyPrinterCb);
-
 
 TagsTest::TagsTest ()
   : Test ("Tags")
@@ -311,7 +337,7 @@
 
   // build initial tag.
   Tags tags;
-  struct myTagA a;
+  myTagA a;
   a.a = 10;
   tags.Add (a);
   a.a = 0;
@@ -321,12 +347,12 @@
       ok = false;
     }
   g_a = false;
-  tags.PrettyPrint (std::cout);
+  tags.Print (std::cout, "");
   if (!g_a)
     {
       ok = false;
     }
-  struct myTagB b;
+  myTagB b;
   b.b = 0xff;
   tags.Add (b);
   b.b = 0;
@@ -337,7 +363,7 @@
     }
   g_b = false;
   g_a = false;
-  tags.PrettyPrint (std::cout);
+  tags.Print (std::cout, "");
   if (!g_a || !g_b)
     {
       ok = false;
@@ -346,26 +372,26 @@
   Tags other = tags;
   g_b = false;
   g_a = false;
-  other.PrettyPrint (std::cout);
+  other.Print (std::cout, "");
   if (!g_a || !g_b)
     {
       ok = false;
     }
   g_b = false;
   g_a = false;
-  tags.PrettyPrint (std::cout);
+  tags.Print (std::cout, "");
   if (!g_a || !g_b)
     {
       ok = false;
     }
-  struct myTagA oA;
+  myTagA oA;
   oA.a = 0;
   other.Peek (oA);
   if (oA.a != 10) 
     {
       ok = false;
     }
-  struct myTagB oB;
+  myTagB oB;
   oB.b = 1;
   other.Peek (oB);
   if (oB.b != 0xff) 
@@ -380,7 +406,7 @@
     }
   g_b = false;
   g_a = false;
-  other.PrettyPrint (std::cout);
+  other.Print (std::cout, "");
   if (g_a || !g_b)
     {
       ok = false;
@@ -401,7 +427,7 @@
 
   other = tags;
   Tags another = other;
-  struct myTagC c;
+  myTagC c;
   memset (c.c, 0x66, 16);
   another.Add (c);
   c.c[0] = 0;
@@ -421,12 +447,12 @@
   //struct myInvalidTag invalid;
   //tags.add (&invalid);
 
-  struct myTagZ tagZ;
+  myTagZ tagZ;
   Tags testLastTag;
   tagZ.z = 0;
   testLastTag.Add (tagZ);
   g_z = false;
-  testLastTag.PrettyPrint (std::cout);
+  testLastTag.Print (std::cout, "");
   if (!g_z)
     {
       ok = false;
@@ -440,6 +466,58 @@
     tmp.Remove (smartTag);
   }
 
+  {
+    Tags source;
+    myTagA aSource;
+    aSource.a = 0x66;
+    source.Add (aSource);
+    Buffer buffer;
+    uint32_t serialized = source.GetSerializedSize ();
+    buffer.AddAtStart (serialized);
+    source.Serialize (buffer.Begin (), serialized);
+    Tags dest;
+    dest.Deserialize (buffer.Begin ());
+    myTagA aDest;
+    aDest.a = 0x55;
+    dest.Peek (aDest);
+    if (aDest.a != 0x66)
+      {
+        ok = false;
+      }
+  }
+
+  {
+    Tags source;
+    myTagA aSource;
+    aSource.a = 0x66;
+    source.Add (aSource);
+    myTagZ zSource;
+    zSource.z = 0x77;
+    source.Add (zSource);
+
+    Buffer buffer;
+    uint32_t serialized = source.GetSerializedSize ();
+    buffer.AddAtStart (serialized);
+    source.Serialize (buffer.Begin (), serialized);
+    Tags dest;
+    dest.Deserialize (buffer.Begin ());
+
+    myTagA aDest;
+    aDest.a = 0x55;
+    dest.Peek (aDest);
+    if (aDest.a != 0x66)
+      {
+        ok = false;
+      }
+    myTagZ zDest;
+    zDest.z = 0x44;
+    dest.Peek (zDest);
+    if (zDest.z != 0x44)
+      {
+        ok = false;
+      }
+  }
+
   return ok;
 }
 
--- a/src/common/tags.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/tags.h	Wed Sep 05 18:35:39 2007 +0100
@@ -24,12 +24,10 @@
 #include <stdint.h>
 #include <ostream>
 #include <vector>
+#include "buffer.h"
 
 namespace ns3 {
 
-template <typename T>
-class TagPrettyPrinter;
-
 /**
  * \ingroup constants
  * \brief Tag maximum size
@@ -54,7 +52,10 @@
   template <typename T>
   bool Peek (T &tag) const;
 
-  void PrettyPrint (std::ostream &os);
+  void Print (std::ostream &os, std::string separator) const;
+  uint32_t GetSerializedSize (void) const;
+  void Serialize (Buffer::Iterator i, uint32_t size) const;
+  uint32_t Deserialize (Buffer::Iterator i);
 
   inline void RemoveAll (void);
 
@@ -79,161 +80,39 @@
   struct TagData *m_next;
 };
 
-/**
- * \brief pretty print packet tags
- * 
- * This class is used to register a pretty-printer
- * callback function to print in a nice user-friendly
- * way the content of the target type. To register
- * such a type, all you need to do is instantiate
- * an instance of this type as a static variable.
- */
-template <typename T>
-class TagRegistration {
-public:
-  /**
-   * \param uuid a uuid generated with uuidgen
-   * \param fn a function which can pretty-print an instance
-   *        of type T in the output stream.
-   */
-  TagRegistration<T> (std::string uuid, void(*fn) (T const*, std::ostream &));
-private:
-  static void PrettyPrinterCb (uint8_t *buf, std::ostream &os);
-  static void DestructorCb (uint8_t *buf);
-  static void(*m_prettyPrinter) (T const*, std::ostream &);
-};
-
-}; // namespace ns3
+} // namespace ns3
 
 
 
 /**************************************************************
    An implementation of the templates defined above
  *************************************************************/
+#include "tag-registry.h"
+#include "tag.h"
 #include "ns3/assert.h"
 #include <string>
 
 namespace ns3 {
 
-class TagRegistry {
-public:
-  typedef void (*PrettyPrinter) (uint8_t [Tags::SIZE], std::ostream &);
-  typedef void (*Destructor) (uint8_t [Tags::SIZE]);
-  void Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor);
-  /**
-   * returns a numeric integer which uniquely identifies the input string.
-   * that integer cannot be zero which is a reserved value.
-   */
-  uint32_t LookupUid (std::string uuid);
-  void PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
-  void Destruct (uint32_t uid, uint8_t buf[Tags::SIZE]);
-
-  static TagRegistry *GetInstance (void);
-private:
-  TagRegistry ();
-  struct TagInfoItem
-  {
-    std::string uuid;
-    PrettyPrinter printer;
-    Destructor destructor;
-  };
-  typedef std::vector<struct TagInfoItem> TagsData;
-  typedef std::vector<struct TagInfoItem>::const_iterator TagsDataCI;
-  static bool CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b);
-  bool m_sorted;
-  TagsData m_registry;
-};
-/**
- * The TypeUid class is used to create a mapping Type --> uid
- * Note that we use a static getUuid function which contains a
- * static std::string variable rather than a simpler static
- * member std::string variable to ensure the proper order
- * of initialization when these methods are invoked
- * from the constructor of another static variable.
- */
-template <typename T>
-class TypeUid {
-public:
-  static void Record (std::string uuid);
-  static const uint32_t GetUid (void);
-private:
-  static std::string *GetUuid (void);
-  T m_realType;
-};
-
-template <typename T>
-void TypeUid<T>::Record (std::string uuid)
-{
-  *(GetUuid ()) = uuid;
-}
-
-template <typename T>
-const uint32_t TypeUid<T>::GetUid (void)
-{
-  static const uint32_t uid = TagRegistry::GetInstance ()->
-    LookupUid (*(GetUuid ()));
-  return uid;
-}
-
-template <typename T>
-std::string *TypeUid<T>::GetUuid (void)
-{
-  static std::string uuid;
-  return &uuid;
-}
-
-
-
-/**
- * Implementation of the TagRegistration registration class.
- * It records a callback with the TagRegistry
- * This callback performs type conversion before forwarding
- * the call to the user-provided function.
- */
-template <typename T>
-TagRegistration<T>::TagRegistration (std::string uuid, void (*prettyPrinter) (T const*, std::ostream &))
-{
-  NS_ASSERT (sizeof (T) <= Tags::SIZE);
-  m_prettyPrinter  = prettyPrinter;
-  TagRegistry::GetInstance ()->
-    Record (uuid, &TagRegistration<T>::PrettyPrinterCb, &TagRegistration<T>::DestructorCb);
-  TypeUid<T>::Record (uuid);
-}
-template <typename T>
-void 
-TagRegistration<T>::PrettyPrinterCb (uint8_t *buf, std::ostream &os)
-{
-  NS_ASSERT (sizeof (T) <= Tags::SIZE);
-  T *tag = reinterpret_cast<T *> (buf);
-  (*m_prettyPrinter) (tag, os);
-}
-template <typename T>
-void
-TagRegistration<T>::DestructorCb (uint8_t *buf)
-{
-  T *tag = reinterpret_cast<T *> (buf);
-  tag->~T ();
-}
-template <typename T>
-void (*TagRegistration<T>::m_prettyPrinter) (T const*, std::ostream &) = 0;
-
-
-
-
 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) 
     {
-      NS_ASSERT (cur->m_id != TypeUid<T>::GetUid ());
+      NS_ASSERT (cur->m_id != T::GetUid ());
     }
   struct TagData *newStart = AllocData ();
   newStart->m_count = 1;
   newStart->m_next = 0;
-  newStart->m_id = TypeUid<T>::GetUid ();
+  newStart->m_id = T::GetUid ();
   void *buf = &newStart->m_data;
   new (buf) T (tag);
   newStart->m_next = m_next;
@@ -244,18 +123,26 @@
 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 (TypeUid<T>::GetUid ());
+  return Remove (T::GetUid ());
 }
 
 template <typename T>
 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) 
     {
-      if (cur->m_id == TypeUid<T>::GetUid ()) 
+      if (cur->m_id == T::GetUid ()) 
         {
           /* found tag */
           T *data = reinterpret_cast<T *> (&cur->m_data);
@@ -315,16 +202,14 @@
         }
       if (prev != 0) 
         {
-          TagRegistry::GetInstance ()->
-            Destruct (prev->m_id, prev->m_data);
+          TagRegistry::Destruct (prev->m_id, prev->m_data);
           FreeData (prev);
         }
       prev = cur;
     }
   if (prev != 0) 
     {
-      TagRegistry::GetInstance ()->
-        Destruct (prev->m_id, prev->m_data);
+      TagRegistry::Destruct (prev->m_id, prev->m_data);
       FreeData (prev);
     }
   m_next = 0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/trace-context-element.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/trace-context.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -19,12 +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 {
 
-std::vector<uint8_t> TraceContext::m_sizes;
-
 TraceContext::TraceContext ()
   : m_data (0)
 {}
@@ -68,12 +67,6 @@
     }
 }
 
-uint8_t 
-TraceContext::GetSize (uint8_t uid)
-{
-  return m_sizes[uid];
-}
-
 void 
 TraceContext::Add (TraceContext const &o)
 {
@@ -81,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)
@@ -116,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];
@@ -131,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)
@@ -201,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);
@@ -212,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)
     {
-      m_sizes.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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/trace-context.h	Wed Sep 05 18:35:39 2007 +0100
@@ -24,6 +24,7 @@
 #include <stdint.h>
 #include <vector>
 #include "ns3/fatal-error.h"
+#include "trace-context-element.h"
 
 namespace ns3 {
 
@@ -77,25 +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;
 
-  static std::vector<uint8_t> m_sizes;
   struct Data {
     uint16_t count;
     uint16_t size;
@@ -111,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.");
@@ -122,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");
@@ -133,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 ();
-  m_sizes.push_back (sizeof (T));
-  return uid;
-}
-
 }//namespace ns3
 
 #endif /* TRACE_CONTEXT_H */
--- a/src/common/trace-root.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/trace-root.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/trace-root.h	Wed Sep 05 18:35:39 2007 +0100
@@ -328,9 +328,6 @@
                         Callback<TraceResolver *,TraceContext const &> createResolver);
 private:
   static CompositeTraceResolver *GetComposite (void);
-  enum TraceType {
-    NOTHING,
-  };
 };
 
 }// namespace ns3
--- a/src/common/trailer.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/trailer.h	Wed Sep 05 18:35:39 2007 +0100
@@ -22,7 +22,28 @@
 #ifndef TRAILER_H
 #define TRAILER_H
 
-#include "chunk.h"
+#include "chunk-registry.h"
+
+/**
+ * \relates ns3::Trailer
+ * \brief this macro should be instantiated exactly once for each
+ *        new type of Trailer
+ *
+ * This macro will ensure that your new Trailer type is registered
+ * within the packet trailer 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_TRAILER_ENSURE_REGISTERED(x)          \
+static class thisisaveryverylongclassname ##x    \
+{                                                \
+ public:                                         \
+  thisisaveryverylongclassname ##x ()            \
+    { uint32_t uid; uid = x::GetUid ();}         \
+} g_thisisanotherveryveryverylongname ##x;
 
 namespace ns3 {
 
@@ -30,98 +51,66 @@
  * \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
+ * 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.
  *
- * 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 ();
-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;
+class Trailer 
+{
+protected:
+  template <typename T>
+  static uint32_t AllocateUid (std::string uidString);
 };
 
-}; // namespace ns3
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+uint32_t 
+Trailer::AllocateUid (std::string uidString)
+{
+  return ChunkRegistry::RegisterTrailer<T> (uidString);
+}
+
+
+} // namespace ns3
 
 #endif /* TRAILER_H */
--- a/src/common/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/common/wscript	Wed Sep 05 18:35:39 2007 +0100
@@ -1,22 +1,20 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    common = bld.create_obj('cpp', 'shlib')
-    common.name = 'ns3-common'
-    common.target = common.name
-    common.uselib_local = ['ns3-core', 'ns3-simulator']
+    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',
@@ -28,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',
@@ -41,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.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "assert.h"
-
-namespace ns3 {
-
-void
-AssertBreakpoint (void)
-{
-  int *a = 0;
-  /**
-   * we test here to allow a debugger to change the value of
-   * the variable 'a' to allow the debugger to avoid the 
-   * subsequent segfault.
-   */
-  if (a == 0)
-    {
-      *a = 0;
-    }
-}
-
-}//namespace ns3
--- a/src/core/assert.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/assert.h	Wed Sep 05 18:35:39 2007 +0100
@@ -21,6 +21,12 @@
 #ifndef ASSERT_H
 #define ASSERT_H
 
+#ifdef NS3_ASSERT_ENABLE
+
+#include <iostream>
+
+#include "breakpoint.h"
+
 /**
  * \defgroup assert Assert
  * \brief assert functions and macros
@@ -32,25 +38,6 @@
  * removed in optimized builds.
  */
 
-namespace ns3 {
-
-/**
- * \ingroup debugging
- *
- * When an NS_ASSERT cannot verify its condition, 
- * this function is called. This is where you should
- * be able to put a breakpoint with a debugger if
- * you want to catch assertions before the program 
- * halts.
- */
-void AssertBreakpoint (void);
-
-}//namespace ns3
-
-#ifdef NS3_ASSERT_ENABLE
-
-#include <iostream>
-
 /**
  * \ingroup assert
  * \param condition condition to verifiy.
@@ -65,10 +52,10 @@
     {                                                           \
       if (!(condition))                                         \
         {                                                       \
-          std::cout << "assert failed. file=" << __FILE__ <<    \
+          std::cerr << "assert failed. file=" << __FILE__ <<    \
             ", line=" << __LINE__ << ", cond=\""#condition <<   \
             "\"" << std::endl;                                  \
-          ns3::AssertBreakpoint ();                             \
+          NS_BREAKPOINT ();                                     \
         }                                                       \
     }                                                           \
   while (false)
@@ -88,8 +75,8 @@
     {                                           \
       if (!(condition))                         \
         {                                       \
-          std::cout << message << std::endl;    \
-          ns3::AssertBreakpoint ();             \
+          std::cerr << message << std::endl;    \
+          NS_BREAKPOINT ();                     \
         }                                       \
     }                                           \
   while (false)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/breakpoint.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,58 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INRIA, INESC Porto
+ * 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>
+ * Author: Gustavo Carneiro <gjc@inescporto.pt>
+ */
+
+#include "breakpoint.h"
+#include "ns3/core-config.h"
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
+
+namespace ns3 {
+
+#if defined (HAVE_SIGNAL_H) && defined (SIGTRAP)
+
+void
+BreakpointFallback (void)
+{
+  raise (SIGTRAP);
+}
+
+#else
+
+void
+BreakpointFallback (void)
+{
+  int *a = 0;
+  /**
+   * we test here to allow a debugger to change the value of
+   * the variable 'a' to allow the debugger to avoid the 
+   * subsequent segfault.
+   */
+  if (a == 0)
+    {
+      *a = 0;
+    }
+}
+
+#endif // HAVE_SIGNAL_H
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/breakpoint.h	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,76 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2006,2007 INESC Porto, 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: Gustavo Carneiro <gjc@inescporto.pt>
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef BREAKPOINT_H
+#define BREAKPOINT_H
+
+namespace ns3 {
+
+/* Hacker macro to place breakpoints for selected machines.
+ * Actual use is strongly discouraged of course ;)
+ * Copied from GLib 2.12.9.
+ * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+/**
+ * \ingroup debugging
+ *
+ * Inserts a breakpoint instruction (or equivalent system call) into
+ * the code for selected machines.  When an NS_ASSERT cannot verify its condition, 
+ * this macro is used. Falls back to calling
+ * AssertBreakpoint() for architectures where breakpoint assembly
+ * instructions are not supported.
+ */
+#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) && defined (__GNUC__) && __GNUC__ >= 2
+#  define NS_BREAKPOINT() \
+   do{ __asm__ __volatile__ ("int $03"); }while(false)
+#elif defined (_MSC_VER) && defined (_M_IX86)
+#  define NS_BREAKPOINT() \
+   do{ __asm int 3h }while(false)
+#elif defined (__alpha__) && !defined(__osf__) && defined (__GNUC__) && __GNUC__ >= 2
+#  define NS_BREAKPOINT() \
+   do{ __asm__ __volatile__ ("bpt"); }while(false)
+#else	/* !__i386__ && !__alpha__ */
+#  define NS_BREAKPOINT()    ns3::BreakpointFallback ()
+#endif
+
+/**
+ * \brief fallback breakpoint function
+ *
+ * This function is used by the NS_BREAKPOINT() macro as a fallback
+ * for when breakpoint assembly instructions are not available.  It
+ * attempts to halt program execution either by a raising SIGTRAP, on
+ * unix systems, or by dereferencing a null pointer.
+ * 
+ * Normally you should not call this function directly.
+ */
+void BreakpointFallback (void);
+
+
+}//namespace ns3
+
+
+#endif /* BREAKPOINT_H */
--- a/src/core/callback.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/callback.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/component-manager.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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/debug.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/debug.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -24,6 +24,7 @@
 #include "debug.h"
 #include "assert.h"
 #include "ns3/core-config.h"
+#include "fatal-error.h"
 
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
@@ -53,6 +54,7 @@
     {
       return;
     }
+  bool allFound = true;
   std::string env = envVar;
   std::string::size_type cur = 0;
   std::string::size_type next = 0;
@@ -88,7 +90,7 @@
         }
       if (!found)
         {
-          std::cout << "No debug component named=\"" << tmp << "\"" << std::endl;
+          allFound = false;
         }
       if (next == std::string::npos)
         {
@@ -100,6 +102,11 @@
           break;
         }
     }
+  if (allFound)
+    {
+      g_firstDebug = true;
+    }
+  
 #endif
 }
 
@@ -122,7 +129,6 @@
   if (g_firstDebug) 
     {
       DebugComponentEnableEnvVar ();
-      g_firstDebug = false;
     }
   return m_isEnabled;
 }
--- a/src/core/debug.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/debug.h	Wed Sep 05 18:35:39 2007 +0100
@@ -110,7 +110,7 @@
     {                                           \
       if (g_debug.IsEnabled ())			\
         {                                       \
-          std::cout << msg << std::endl;        \
+          std::cerr << msg << std::endl;        \
         }                                       \
     }                                           \
   while (false)
@@ -125,7 +125,7 @@
 #define NS_DEBUG_UNCOND(msg)         \
   do                                 \
     {                                \
-      std::cout << msg << std::endl; \
+      std::cerr << msg << std::endl; \
     }                                \
   while (false)
 
--- a/src/core/default-value.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/default-value.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -23,6 +23,52 @@
 
 namespace ns3 {
 
+namespace DefaultValue {
+
+enum BindStatus {
+  OK,
+  INVALID_VALUE,
+  NOT_FOUND
+};
+
+
+static 
+enum BindStatus
+BindSafe (std::string name, std::string value)
+{
+  for (DefaultValueList::Iterator i = DefaultValueList::Begin ();
+       i != DefaultValueList::End (); i++)
+    {
+      DefaultValueBase *cur = *i;
+      if (cur->GetName () == name)
+	{
+	  if (!cur->ParseValue (value))
+	    {
+	      return INVALID_VALUE;
+	    }
+	  return OK;
+	}
+    }
+  return NOT_FOUND;
+}
+
+void
+Bind (std::string name, std::string value)
+{
+  switch (BindSafe (name, value)) {
+  case INVALID_VALUE:
+    NS_FATAL_ERROR ("Invalid value: "<<name<<"="<<value);
+    break;
+  case NOT_FOUND:
+    NS_FATAL_ERROR ("No registered DefaultValue=\"" << name << "\"");
+    break;
+  case OK:
+    break;
+  }
+}
+
+}
+
 DefaultValueBase::DefaultValueBase (const std::string &name,
 				    const std::string &help)
   : m_name (name),
@@ -112,48 +158,6 @@
   return &list;
 }
 
-enum BindStatus {
-  OK,
-  INVALID_VALUE,
-  NOT_FOUND
-};
-
-
-static 
-enum BindStatus
-BindSafe (std::string name, std::string value)
-{
-  for (DefaultValueList::Iterator i = DefaultValueList::Begin ();
-       i != DefaultValueList::End (); i++)
-    {
-      DefaultValueBase *cur = *i;
-      if (cur->GetName () == name)
-	{
-	  if (!cur->ParseValue (value))
-	    {
-	      return INVALID_VALUE;
-	    }
-	  return OK;
-	}
-    }
-  return NOT_FOUND;
-}
-
-void
-Bind (std::string name, std::string value)
-{
-  switch (BindSafe (name, value)) {
-  case INVALID_VALUE:
-    NS_FATAL_ERROR ("Invalid value: "<<name<<"="<<value);
-    break;
-  case NOT_FOUND:
-    NS_FATAL_ERROR ("No registered DefaultValue=\"" << name << "\"");
-    break;
-  case OK:
-    break;
-  }
-}
-
 BooleanDefaultValue::BooleanDefaultValue (std::string name,
 					  std::string help,
 					  bool defaultValue)
@@ -341,85 +345,40 @@
 bool 
 DefaultValueTest::RunTests (void)
 {
-  bool ok = true;
+  bool result = true;
 
   BooleanDefaultValue a ("bool-a", "help a", true);
-  if (!a.GetValue ())
-    {
-      ok = false;
-    }
-  Bind ("bool-a", "false");
-  if (a.GetValue ())
-    {
-      ok = false;
-    }
+  NS_TEST_ASSERT (a.GetValue ());
+  DefaultValue::Bind ("bool-a", "false");
+  NS_TEST_ASSERT (!a.GetValue ());
   BooleanDefaultValue b ("bool-b", "help b", false);
-  Bind ("bool-b", "true");
-  if (!b.GetValue ())
-    {
-      ok = false;
-    }
-  Bind ("bool-b", "0");
-  if (b.GetValue ())
-    {
-      ok = false;
-    }
-  Bind ("bool-b", "1");
-  if (!b.GetValue ())
-    {
-      ok = false;
-    }
-  Bind ("bool-b", "f");
-  if (b.GetValue ())
-    {
-      ok = false;
-    }
-  Bind ("bool-b", "t");
-  if (!b.GetValue ())
-    {
-      ok = false;
-    }
+  DefaultValue::Bind ("bool-b", "true");
+  NS_TEST_ASSERT (b.GetValue ());
+  DefaultValue::Bind ("bool-b", "0");
+  NS_TEST_ASSERT (!b.GetValue ());
+  DefaultValue::Bind ("bool-b", "1");
+  NS_TEST_ASSERT (b.GetValue ());
+  DefaultValue::Bind ("bool-b", "f");
+  NS_TEST_ASSERT (!b.GetValue ());
+  DefaultValue::Bind ("bool-b", "t");
+  NS_TEST_ASSERT (b.GetValue ());
 
-  Bind ("bool-b", "false");
-  if (b.GetValue ())
-    {
-      ok = false;
-    }
-  if (BindSafe ("bool-b", "tr") != INVALID_VALUE)
-    {
-      ok = false;
-    }
+  DefaultValue::Bind ("bool-b", "false");
+  NS_TEST_ASSERT (!b.GetValue ());
+  NS_TEST_ASSERT_EQUAL (DefaultValue::BindSafe ("bool-b", "tr"), DefaultValue::INVALID_VALUE)
 
-  NumericDefaultValue<int> i ("test-i", "help-i", -1);
-  if (i.GetValue () != -1)
-    {
-      ok = false;
-    }  
-  Bind ("test-i", "-2");
-  if (i.GetValue () != -2)
-    {
-      ok = false;
-    }
-  Bind ("test-i", "+2");
-  if (i.GetValue () != 2)
-    {
-      ok = false;
-    }
-  if (i.GetType () != "int32_t(-2147483648:2147483647)")
-    {
-      ok = false;
-    }
+  NumericDefaultValue<int32_t> i ("test-i", "help-i", -1);
+  NS_TEST_ASSERT_EQUAL (i.GetValue (), -1);
+  DefaultValue::Bind ("test-i", "-2");
+  NS_TEST_ASSERT_EQUAL (i.GetValue (), -2);
+  DefaultValue::Bind ("test-i", "+2");
+  NS_TEST_ASSERT_EQUAL (i.GetValue (), 2);
+  NS_TEST_ASSERT_EQUAL (i.GetType (), "int32_t(-2147483648:2147483647)");
   NumericDefaultValue<uint32_t> ui32 ("test-ui32", "help-ui32", 10);
-  if (ui32.GetType () != "uint32_t(0:4294967295)")
-    {
-      ok = false;
-    }
-  NumericDefaultValue<char> c ("test-c", "help-c", 10);
-  if (c.GetValue () != 10)
-    {
-      ok = false;
-    }
-  Bind ("test-c", "257");  
+  NS_TEST_ASSERT_EQUAL (ui32.GetType (), "uint32_t(0:4294967295)");
+  NumericDefaultValue<int8_t> c ("test-c", "help-c", 10);
+  NS_TEST_ASSERT_EQUAL (c.GetValue (), 10);
+  DefaultValue::Bind ("test-c", "257");  
   NumericDefaultValue<float> x ("test-x", "help-x", 10.0);
   NumericDefaultValue<double> y ("test-y", "help-y", 10.0);
 
@@ -429,19 +388,10 @@
 				   MY_ENUM_A, "A",
 				   MY_ENUM_B, "B",
 				   0, (void*)0);
-  if (e.GetValue () != MY_ENUM_C)
-    {
-      ok = false;
-    }
-  Bind ("test-e", "B");
-  if (e.GetValue () != MY_ENUM_B)
-    {
-      ok = false;
-    }
-  if (BindSafe ("test-e", "D") != INVALID_VALUE)
-    {
-      ok = false;
-    }
+  NS_TEST_ASSERT_EQUAL (e.GetValue (), MY_ENUM_C);
+  DefaultValue::Bind ("test-e", "B");
+  NS_TEST_ASSERT_EQUAL (e.GetValue (), MY_ENUM_B);
+  NS_TEST_ASSERT_EQUAL (DefaultValue::BindSafe ("test-e", "D"), DefaultValue::INVALID_VALUE);
 
   class MyEnumSubclass : public EnumDefaultValue<enum MyEnum>
   {
@@ -456,15 +406,9 @@
       AddPossibleValue (MY_ENUM_D, "D");
     }
   } e1 ;
-  if (e1.GetValue () != MY_ENUM_B)
-    {
-      ok = false;
-    }
-  Bind ("test-e1", "D");
-  if (e1.GetValue () != MY_ENUM_D)
-    {
-      ok = false;
-    }
+  NS_TEST_ASSERT_EQUAL (e1.GetValue (), MY_ENUM_B);
+  DefaultValue::Bind ("test-e1", "D");
+  NS_TEST_ASSERT_EQUAL (e1.GetValue (), MY_ENUM_D);
 
   DefaultValueList::Remove ("test-e1");
   DefaultValueList::Remove ("test-e");
@@ -474,7 +418,7 @@
   DefaultValueList::Remove ("test-c");
   DefaultValueList::Remove ("test-ui32");
   
-  return ok;
+  return result;
 }
 
 static DefaultValueTest g_default_value_tests;
--- a/src/core/default-value.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/default-value.h	Wed Sep 05 18:35:39 2007 +0100
@@ -31,6 +31,25 @@
 
 namespace ns3 {
 
+namespace DefaultValue
+{
+
+/**
+ * \ingroup config
+ * \param name name of variable to bind
+ * \param value value to bind to the specified variable
+ *
+ * If the variable name does not match any existing
+ * variable or if the value is not compatible with
+ * the variable type, this function will abort
+ * at runtime and print an error message detailing
+ * which variable or value triggered the problem.
+ */
+void Bind (std::string name, std::string value);
+
+}
+
+
 class DefaultValueBase
 {
 public:
@@ -84,19 +103,6 @@
 };
 
 /**
- * \ingroup config
- * \param name name of variable to bind
- * \param value value to bind to the specified variable
- *
- * If the variable name does not match any existing
- * variable or if the value is not compatible with
- * the variable type, this function will abort
- * at runtime and print an error message detailing
- * which variable or value triggered the problem.
- */
-void Bind (std::string name, std::string value);
-
-/**
  * \brief A Boolean variable for ns3::Bind
  * \ingroup config
  *
--- a/src/core/fatal-error.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/fatal-error.h	Wed Sep 05 18:35:39 2007 +0100
@@ -21,7 +21,7 @@
 #ifndef FATAL_ERROR_H
 #define FATAL_ERROR_H
 
-#include "assert.h"
+#include "breakpoint.h"
 #include <iostream>
 
 /**
@@ -32,15 +32,15 @@
  *
  * When this macro is hit at runtime, the user-specified 
  * error message is output and the program is halted by calling
- * the ns3::AssertBreakpoint function. This macro is enabled
+ * the NS_DEBUG_BREAKPOINT macro. This macro is enabled
  * unconditionally in all builds, including debug and optimized 
  * builds.
  */
 #define NS_FATAL_ERROR(msg)				\
   do                                                    \
     {                                                   \
-      std::cout << msg << std::endl;			\
-      ns3::AssertBreakpoint ();                         \
+      std::cerr << msg << std::endl;			\
+      NS_BREAKPOINT ();                                 \
     }                                                   \
   while (false)
 
--- a/src/core/ptr.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/ptr.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -28,9 +28,14 @@
 
 namespace ns3 {
 
+template <typename T>
+void Foo (void) {}
+
+
 class NoCount : public Object
 {
 public:
+  NoCount (void (*fn) (void));
   NoCount (Callback<void> cb);
   ~NoCount ();
   void Nothing (void) const;
@@ -292,12 +297,22 @@
     callback ();
   }
 
+
 #if 0
   // as expected, fails compilation.
   {
     Ptr<const Object> p = Create<NoCount> (cb);
     Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
   }
+  // local types are not allowed as arguments to a template.
+  {
+    class B
+    {
+    public:
+      B () {}
+    };
+    Foo<B> ();
+  }
 #endif
   
 
--- a/src/core/ptr.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/ptr.h	Wed Sep 05 18:35:39 2007 +0100
@@ -65,7 +65,7 @@
   template <typename U>
   friend U *PeekPointer (const Ptr<U> &p);
 
-  void Acquire (void) const;
+  inline void Acquire (void) const;
 public:
   /**
    * Create an empty smart pointer
@@ -81,7 +81,16 @@
    * same, so that object is deleted if no more references to it
    * remain.
    */
-  Ptr (T *ptr);
+  Ptr (T *ptr);  
+  /**
+   * \param ptr raw pointer to manage
+   * \param ref if set to true, this method calls Ref, otherwise,
+   *        it does not call Ref.
+   *    
+   * Create a smart pointer which points to the object pointed to by
+   * the input raw pointer ptr.
+   */
+  Ptr (T *ptr, bool ref);
   Ptr (Ptr const&o);
   // allow conversions from T to T const.
   template <typename U>
@@ -379,6 +388,16 @@
 }
 
 template <typename T>
+Ptr<T>::Ptr (T *ptr, bool ref) 
+  : m_ptr (ptr)
+{
+  if (ref)
+    {
+      Acquire ();
+    }
+}
+
+template <typename T>
 Ptr<T>::Ptr (Ptr const&o) 
   : m_ptr (PeekPointer (o))
 {
--- a/src/core/random-variable.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/random-variable.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -108,8 +108,8 @@
 {
   if (RandomVariable::globalSeedSet)
     {
-      cout << "Random number generator already initialized!" << endl;
-      cout << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
+      cerr << "Random number generator already initialized!" << endl;
+      cerr << "Call to RandomVariable::UseGlobalSeed() ignored" << endl;
       return;
     }
   RandomVariable::globalSeed[0] = s0;
@@ -537,7 +537,7 @@
       ValueCDF& current = emp[i];
       if (current.value < prior.value || current.cdf < prior.cdf)
         { // Error
-          cout << "Empirical Dist error,"
+          cerr << "Empirical Dist error,"
                << " current value " << current.value
                << " prior value "   << prior.value
                << " current cdf "   << current.cdf
--- a/src/core/random-variable.h	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/random-variable.h	Wed Sep 05 18:35:39 2007 +0100
@@ -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/core/rng-stream.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/rng-stream.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -269,11 +269,11 @@
     }
     for (i = 3; i < 6; ++i) {
         if (seed[i] >= m2) {
-	  cout << "Seed[" << i << "] = " << seed[i] << endl; 
-            cerr << "*****************************************\n\n"
-                 << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
-                 << "\n\n*****************************************\n\n";
-            return (false);
+	  cerr << "Seed[" << i << "] = " << seed[i] << endl; 
+          cerr << "*****************************************\n\n"
+               << "ERROR: Seed[" << i << "] >= 4294944443, Seed is not set."
+               << "\n\n*****************************************\n\n";
+          return (false);
         }
     }
     if (seed[0] == 0 && seed[1] == 0 && seed[2] == 0) {
--- a/src/core/uid-manager.cc	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/uid-manager.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -20,6 +20,7 @@
  */
 #include "uid-manager.h"
 #include "ns3/fatal-error.h"
+#include "ns3/assert.h"
 
 
 namespace ns3 {
--- a/src/core/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ b/src/core/wscript	Wed Sep 05 18:35:39 2007 +0100
@@ -15,18 +15,22 @@
     e.define = 'HAVE_GETENV'
     e.run()
 
+    e = conf.create_header_configurator()
+    e.mandatory = False
+    e.name = 'signal.h'
+    e.define = 'HAVE_SIGNAL_H'
+    e.run()
+
     conf.write_config_header('ns3/core-config.h')
 
 
 
 def build(bld):
-    core = bld.create_obj('cpp', 'shlib')
-    core.name = 'ns3-core'
-    core.target = core.name
+    core = bld.create_ns3_module('core')
     core.source = [
         'callback-test.cc',
         'debug.cc',
-        'assert.cc',
+        'breakpoint.cc',
         'ptr.cc',
         'object.cc',
         'test.cc',
@@ -58,6 +62,7 @@
         'object.h',
         'debug.h',
         'assert.h',
+        'breakpoint.h',
         'fatal-error.h',
         'test.h',
         'random-variable.h',
--- a/src/devices/csma-cd/backoff.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007, Emmanuelle Laprise
- * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
- */
-
-#include "backoff.h"
-
-namespace ns3 {
-
-Backoff::Backoff() 
-{
-  m_slotTime = MicroSeconds(1);
-  m_minSlots = 1;
-  m_maxSlots = 1000;
-  m_ceiling = 10;
-  m_maxRetries = 1000;
-
-  ResetBackoffTime();
-}
-
-Backoff::Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots,
-                 uint32_t ceiling, uint32_t maxRetries)
-{
-  m_slotTime = slotTime;
-  m_minSlots = minSlots;
-  m_maxSlots = maxSlots;
-  m_ceiling = ceiling;
-  m_maxRetries = maxRetries;
-}  
-
-Time
-Backoff::GetBackoffTime (void)
-{
-  Time backoff;
-  uint32_t ceiling;
-
-  if ((m_ceiling > 0) &&(m_numBackoffRetries > m_ceiling))
-    ceiling = m_ceiling;
-  else
-    ceiling = m_numBackoffRetries;
-
-  uint32_t minSlot = m_minSlots;
-  uint32_t maxSlot = (uint32_t)pow(2, ceiling) - 1;
-  if (maxSlot > m_maxSlots)
-    maxSlot = m_maxSlots;
-
-  uint32_t backoffSlots = 
-    (uint32_t)UniformVariable::GetSingleValue(minSlot, maxSlot);
-
-  backoff = Scalar(backoffSlots) * m_slotTime;
-  return (backoff);
-}
-
-void Backoff::ResetBackoffTime (void)
-{
-  m_numBackoffRetries = 0;
-}
-
-bool Backoff::MaxRetriesReached(void) {
-  return (m_numBackoffRetries >= m_maxRetries);
-}
-
-void Backoff::IncrNumRetries(void) {
-  m_numBackoffRetries++;
-}
-
-} // namespace ns3
--- a/src/devices/csma-cd/backoff.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Emmanuelle Laprise
- *
- * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca
- * Derived from the p2p net device file
-Transmi */
-
-#ifndef BACKOFF_H
-#define BACKOFF_H
-
-#include <stdint.h>
-#include "ns3/nstime.h"
-#include "ns3/random-variable.h"
-
-namespace ns3 {
-
-  /**
-   * \brief The backoff class is used for calculating backoff times
-   * when many net devices can write to the same channel
-   *
-   */
-
-class Backoff {
-public:
-  uint32_t m_minSlots; // Minimum number of backoff slots (when
-                       // multiplied by m_slotTime, determines minimum
-                       // backoff time)
-  uint32_t m_maxSlots; // Maximim number of backoff slots (when
-                       // multiplied by m_slotTime, determines
-                       // maximum backoff time)
-  uint32_t m_ceiling;  // Caps the exponential function when the
-                       // number of retries reaches m_ceiling
-  uint32_t m_maxRetries; // Maximum number of transmission retries
-                         // before the packet is dropped.
-  Time     m_slotTime; // Length of one slot. A slot time, it usually
-                       // the packet transmission time, if the packet
-                       // size is fixed.
-
-  Backoff();
-  Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots, 
-          uint32_t ceiling, uint32_t maxRetries);
-
-  /**
-   * \return The amount of time that the net device should wait before
-   * trying to retransmit the packet
-   */
-  Time GetBackoffTime();
-  /**
-   * Indicates to the backoff object that the last packet was
-   * successfully transmitted and that the number of retries should be
-   * reset to 0.
-   */
-  void ResetBackoffTime();
-  /**
-   * \return True if the maximum number of retries has been reached
-   */
-  bool MaxRetriesReached();
-  /**
-   * Increments the number of retries by 1.
-   */
-  void IncrNumRetries();
-
-private:
-  uint32_t m_numBackoffRetries; // Number of times that the
-                                // transmitter has tried to
-                                // unsuccessfully transmit the current
-                                // packet
-};
-
-}; // namespace ns3
-
-#endif // BACKOFF_H
-
--- a/src/devices/csma-cd/csma-cd-channel.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,371 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Emmanuelle Laprise
- * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
- */
-
-#include "csma-cd-channel.h"
-#include "csma-cd-net-device.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-#include "ns3/debug.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("CsmaCdChannel");
-
-namespace ns3 {
-
-CsmaCdDeviceRec::CsmaCdDeviceRec()
-{
-  active = false;
-}
-
-CsmaCdDeviceRec::CsmaCdDeviceRec(Ptr<CsmaCdNetDevice> device)
-{
-  devicePtr = device; 
-  active = true;
-}
-
-bool
-CsmaCdDeviceRec::IsActive() {
-  return active;
-}
-
-
-//
-// By default, you get a channel with the name "CsmaCd Channel" that 
-// has an "infitely" fast transmission speed and zero delay.
-CsmaCdChannel::CsmaCdChannel()
-: 
-  Channel ("CsmaCd Channel"), 
-  m_bps (DataRate(0xffffffff)),
-  m_delay (Seconds(0))
-{
-  NS_DEBUG("CsmaCdChannel::CsmaCdChannel ()");
-  Init();
-}
-
-CsmaCdChannel::CsmaCdChannel(
-  const DataRate& bps, 
-  const Time& delay)
-: 
-  Channel ("CsmaCd Channel"), 
-  m_bps (bps),
-  m_delay (delay)
-{
-  NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << Channel::GetName() 
-    << ", " << bps.GetBitRate() << ", " << delay << ")");
-  Init();
-}
-
-CsmaCdChannel::CsmaCdChannel(
-  const std::string& name,
-  const DataRate& bps, 
-  const Time& delay)
-: 
-  Channel (name),
-  m_bps (bps), 
-  m_delay (delay)
-{
-  NS_DEBUG("CsmaCdChannel::CsmaCdChannel (" << name << ", " << 
-           bps.GetBitRate() << ", " << delay << ")");
-  Init();
-}
-
-void CsmaCdChannel::Init() {
-  m_state = IDLE;
-  m_deviceList.clear();
-}
-
-int32_t
-CsmaCdChannel::Attach(Ptr<CsmaCdNetDevice> device)
-{
-  NS_DEBUG("CsmaCdChannel::Attach (" << device << ")");
-  NS_ASSERT(device != 0);
-
-  CsmaCdDeviceRec rec(device);
-  
-  m_deviceList.push_back(rec);
-  return (m_deviceList.size() - 1);
-}
-
-bool
-CsmaCdChannel::Reattach(Ptr<CsmaCdNetDevice> device)
-{
-  NS_DEBUG("CsmaCdChannel::Reattach (" << device << ")");
-  NS_ASSERT(device != 0);
-
-  std::vector<CsmaCdDeviceRec>::iterator it;
-  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
-    {
-      if (it->devicePtr == device) 
-        {
-          if (!it->active) 
-            {
-              it->active = true;
-              return true;
-            } 
-          else 
-            {
-              return false;
-            }
-        }
-    }
-  return false;
-}
-
-bool
-CsmaCdChannel::Reattach(uint32_t deviceId)
-{
-  NS_DEBUG("CsmaCdChannel::Reattach (" << deviceId << ")");
-  if (deviceId < m_deviceList.size())
-    {
-      return false;
-    }
-
-  if (m_deviceList[deviceId].active)
-    {
-      return false;
-    } 
-  else 
-    {
-      m_deviceList[deviceId].active = true;
-      return true;
-    }
-}
-
-bool
-CsmaCdChannel::Detach(uint32_t deviceId)
-{
-  NS_DEBUG("CsmaCdChannel::Detach (" << deviceId << ")");
-
-  if (deviceId < m_deviceList.size())
-    {
-      if (!m_deviceList[deviceId].active)
-        {
-          NS_DEBUG("CsmaCdChannel::Detach Device is already detached (" 
-                   << deviceId << ")");
-          return false;
-        }
-
-      m_deviceList[deviceId].active = false;
-      if ((m_state == TRANSMITTING) && (m_currentSrc == deviceId))
-        {
-          NS_DEBUG("CsmaCdChannel::Detach Device is currently"
-                   << "transmitting (" << deviceId << ")");
-          // Here we will need to place a warning in the packet
-        }
-
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-bool
-CsmaCdChannel::Detach(Ptr<CsmaCdNetDevice> device)
-{
-  NS_DEBUG("CsmaCdChannel::Detach (" << device << ")");
-  NS_ASSERT(device != 0);
-
-  std::vector<CsmaCdDeviceRec>::iterator it;
-  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
-    {
-      if ((it->devicePtr == device) && (it->active)) 
-        {
-          it->active = false;
-          return true;
-        }
-    }
-  return false;
-}
-
-bool
-CsmaCdChannel::TransmitStart(Packet& p, uint32_t srcId)
-{
-  NS_DEBUG ("CsmaCdChannel::TransmitStart (" << &p << ", " << srcId 
-            << ")");
-  NS_DEBUG ("CsmaCdChannel::TransmitStart (): UID is " << 
-            p.GetUid () << ")");
-
-  if (m_state != IDLE)
-    {
-      NS_DEBUG("CsmaCdChannel::TransmitStart (): state is not IDLE");
-      return false;
-    }
-
-  if (!IsActive(srcId))
-    {
-      NS_DEBUG("CsmaCdChannel::TransmitStart (): ERROR: Seclected "
-               << "source is not currently attached to network");
-      return false;
-    }
-
-  NS_DEBUG("CsmaCdChannel::TransmitStart (): switch to TRANSMITTING");
-  m_currentPkt = p;
-  m_currentSrc = srcId;
-  m_state = TRANSMITTING;
-  return true;
-}
-
-bool
-CsmaCdChannel::IsActive(uint32_t deviceId) 
-{
-    return (m_deviceList[deviceId].active);
-}
-
-bool
-CsmaCdChannel::TransmitEnd()
-{
-  NS_DEBUG("CsmaCdChannel::TransmitEnd (" << &m_currentPkt << ", " 
-           << m_currentSrc << ")");
-  NS_DEBUG("CsmaCdChannel::TransmitEnd (): UID is " << 
-            m_currentPkt.GetUid () << ")");
-
-  NS_ASSERT(m_state == TRANSMITTING);
-  m_state = PROPAGATING;
-
-  bool retVal = true;
-
-  if (!IsActive(m_currentSrc)) {
-    NS_DEBUG("CsmaCdChannel::TransmitEnd (): ERROR: Seclected source "
-             << "was detached before the end of the transmission");
-    retVal = false;
-  }
-
-  NS_DEBUG ("CsmaCdChannel::TransmitEnd (): Schedule event in " << 
-            m_delay.GetSeconds () << "sec");
-
-  Simulator::Schedule (m_delay,
-                       &CsmaCdChannel::PropagationCompleteEvent,
-                       this);
-  return retVal;
-}
-
-void
-CsmaCdChannel::PropagationCompleteEvent()
-{
-  NS_DEBUG("CsmaCdChannel::PropagationCompleteEvent (" 
-           << &m_currentPkt << ")");
-  NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): UID is " << 
-            m_currentPkt.GetUid () << ")");
-
-  NS_ASSERT(m_state == PROPAGATING);
-  m_state = IDLE;
-
-  NS_DEBUG ("CsmaCdChannel::PropagationCompleteEvent (): Receive");
-  
-  std::vector<CsmaCdDeviceRec>::iterator it;
-  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
-    {
-      if (it->IsActive())
-      {
-        it->devicePtr->Receive (m_currentPkt);
-      }
-    }
-}
-
-
-uint32_t 
-CsmaCdChannel::GetNumActDevices (void)
-{
-  int numActDevices = 0;
-  std::vector<CsmaCdDeviceRec>::iterator it;
-  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
-    {
-      if (it->active)
-        {
-          numActDevices++;
-        }
-    }
-  return numActDevices;
-}
-
-// This is not the number of active devices. This is the total number
-// of devices even if some were detached after.
-uint32_t 
-CsmaCdChannel::GetNDevices (void) const
-{
-  return (m_deviceList.size());
-}
-
-Ptr<NetDevice>
-CsmaCdChannel::GetDevice (uint32_t i) const
-{
-  Ptr< CsmaCdNetDevice > netDevice;
-
-  netDevice = m_deviceList[i].devicePtr;
-  return netDevice;
-}
-
-int32_t
-CsmaCdChannel::GetDeviceNum (Ptr<CsmaCdNetDevice> device)
-{
-  std::vector<CsmaCdDeviceRec>::iterator it;
-  int i = 0;
-  for (it = m_deviceList.begin(); it < m_deviceList.end(); it++) 
-    {
-      if (it->devicePtr == device)
-        {
-          if (it->active) 
-            {
-              return i;
-            } 
-          else 
-            {
-              return -2;
-            }
-        }
-      i++;
-    }
-  return -1;
-}
-
-bool 
-CsmaCdChannel::IsBusy (void)
-{
-  if (m_state == IDLE) 
-    {
-      return false;
-    } 
-  else 
-    {
-      return true;
-    }
-}
-
-DataRate
-CsmaCdChannel::GetDataRate (void)
-{
-  return m_bps;
-}
-
-Time
-CsmaCdChannel::GetDelay (void)
-{
-  return m_delay;
-}
-
-WireState
-CsmaCdChannel::GetState(void)
-{
-  return m_state;
-}
-
-} // namespace ns3
--- a/src/devices/csma-cd/csma-cd-channel.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,307 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Emmanuelle Laprise
- *
- * 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: Emmanuelle Laprise<emmanuelle.laprise@bluekazoo.ca>
- */
-
-#ifndef CSMA_CD_CHANNEL_H
-#define CSMA_CD_CHANNEL_H
-
-#include "ns3/channel.h"
-#include "ns3/ptr.h"
-#include "ns3/packet.h"
-#include "ns3/nstime.h"
-#include "ns3/data-rate.h"
-
-namespace ns3 {
-
-class CsmaCdNetDevice;
-
-  /**
-   * \brief CsmaCdNetDevice Record 
-   *
-   * Stores the information related to each net device that is
-   * connected to the channel. 
-   */
-  class CsmaCdDeviceRec {
-  public:
-    Ptr< CsmaCdNetDevice > devicePtr; /// Pointer to the net device
-    bool                       active;    /// Is net device enabled to TX/RX
-
-    CsmaCdDeviceRec();
-    CsmaCdDeviceRec(Ptr< CsmaCdNetDevice > device);
-    /*
-     * \return If the net device pointed to by the devicePtr is active
-     * and ready to RX/TX.
-     */
-    bool IsActive();                   
-  };
-
-  /**
-   * Current state of the channel
-   */ 
-  enum WireState
-    {
-      IDLE,          /**< Channel is IDLE, no packet is being
-                        transmitted */
-      TRANSMITTING,  /**< Channel is BUSY, a packet is being written
-                        by a net device */
-      PROPAGATING    /**< Channel is BUSY, packet is propagating to
-                        all attached net devices */
-    };
-
-/**
- * \brief CsmaCd Channel.
- *
- * This class represents a simple Csma/Cd channel that can be used
- * when many nodes are connected to one wire. It uses a single busy
- * flag to indicate if the channel is currently in use. It does not
- * take into account the distances between stations or the speed of
- * light to determine collisions.
- *
- * Each net device must query the state of the channel and make sure
- * that it is IDLE before writing a packet to the channel.
- *
- * When the channel is instaniated, the constructor takes parameters
- * for a single speed, in bits per second, and a speed-of-light delay
- * time as a Time object.  When a net device is attached to a channel,
- * it is assigned a device ID, this is in order to facilitate the
- * check that makes sure that a net device that is trying to send a
- * packet to the channel is really connected to this channel
- *
- */
-class CsmaCdChannel : public Channel {
-public:
-  /**
-   * \brief Create a CsmaCdChannel
-   *
-   * By default, you get a channel with the name "CsmaCd Channel" that
-   * has an "infitely" fast transmission speed and zero delay.
-   */
-  CsmaCdChannel ();
-  
-  /**
-   * \brief Create a CsmaCdChannel
-   *
-   * \param bps The bitrate of the channel
-   * \param delay Transmission delay through the channel
-   */  
-  CsmaCdChannel (const DataRate& bps, const Time& delay);
-  
-  /**
-   * \brief Create a CsmaCdChannel
-   *
-   * \param name the name of the channel for identification purposes
-   * \param bps The bitrate of the channel
-   * \param delay Transmission delay through the channel
-   */
-  CsmaCdChannel (const std::string& name,
-                     const DataRate& bps, const Time& delay);
-
-  /**
-   * \brief Attach a given netdevice to this channel
-   *
-   * \param device Device pointer to the netdevice to attach to the channel
-   * \return The assigned device number
-   */
-  int32_t Attach (Ptr<CsmaCdNetDevice> device);
-  /**
-   * \brief Detach a given netdevice from this channel
-   *
-   * The net device is marked as inactive and it is not allowed to
-   * receive or transmit packets
-   *
-   * \param device Device pointer to the netdevice to detach from the channel
-   * \return True if the device is found and attached to the channel,
-   * false if the device is not currently connected to the channel or
-   * can't be found.
-   */
-  bool Detach (Ptr<CsmaCdNetDevice> device);
-  /**
-   * \brief Detach a given netdevice from this channel
-   *
-   * The net device is marked as inactive and it is not allowed to
-   * receive or transmit packets
-   *
-   * \param deviceId The deviceID assigned to the net device when it
-   * was connected to the channel
-   * \return True if the device is found and attached to the channel,
-   * false if the device is not currently connected to the channel or
-   * can't be found.
-   */
-  bool Detach (uint32_t deviceId);
-  /**
-   * \brief Reattach a previously detached net device to the channel
-   *
-   * The net device is marked as active. It is now allowed to receive
-   * or transmit packets. The net device must have been previously
-   * attached to the channel using the attach function.
-   *
-   * \param deviceId The device ID assigned to the net device when it
-   * was connected to the channel
-   * \return True if the device is found and is not attached to the
-   * channel, false if the device is currently connected to the
-   * channel or can't be found.
-   */
-  bool Reattach(uint32_t deviceId);
-  /**
-   * \brief Reattach a previously detached net device to the channel
-   *
-   * The net device is marked as active. It is now allowed to receive
-   * or transmit packets. The net device must have been previously
-   * attached to the channel using the attach function.
-   *
-   * \param device Device pointer to the netdevice to detach from the channel
-   * \return True if the device is found and is not attached to the
-   * channel, false if the device is currently connected to the
-   * channel or can't be found.
-   */
-  bool Reattach(Ptr<CsmaCdNetDevice> device);
-  /**
-   * \brief Start transmitting a packet over the channel
-   *
-   * If the srcId belongs to a net device that is connected to the
-   * channel, packet transmission begins, and the channel becomes busy
-   * until the packet has completely reached all destinations.
-   *
-   * \param p A reference to the packet that will be transmitted over
-   * the channel
-   * \param srcId The device Id of the net device that wants to
-   * transmit on the channel.
-   * \return True if the channel is not busy and the transmitting net
-   * device is currently active.
-   */
-  bool TransmitStart (Packet& p, uint32_t srcId);
-  /**
-   * \brief Indicates that the net device has finished transmitting
-   * the packet over the channel
-   *
-   * The channel will stay busy until the packet has completely
-   * propagated to all net devices attached to the channel. The
-   * TransmitEnd function schedules the PropagationCompleteEvent which
-   * will free the channel for further transmissions. Stores the
-   * packet p as the m_currentPkt, the packet being currently
-   * transmitting.
-   *
-   * \return Returns true unless the source was detached before it
-   * completed its transmission.
-   */
-  bool TransmitEnd ();
-  /**
-   * \brief Indicates that the channel has finished propagating the
-   * current packet. The channel is released and becomes free.
-   *
-   * Calls the receive function of every active net device that is
-   * attached to the channel.
-   */
-  void PropagationCompleteEvent();
-  /**
-   * \return Returns the device number assigned to a net device by the
-   * channel
-   *
-   * \param device Device pointer to the netdevice for which the device
-   * number is needed
-   */
-  int32_t GetDeviceNum (Ptr<CsmaCdNetDevice> device);
-  /**
-   * \return Returns the state of the channel (IDLE -- free,
-   * TRANSMITTING -- busy, PROPAGATING - busy )
-   */
-  WireState GetState();
-
-  /**
-   * \brief Indicates if the channel is busy. The channel will only
-   * accept new packets for transmission if it is not busy.
-   *
-   * \return Returns true if the channel is busy and false if it is
-   * free.
-   */
-  bool IsBusy();
-  
-  /**
-   * \brief Indicates if a net device is currently attached or
-   * detached from the channel.
-   *
-   * \param deviceId The ID that was assigned to the net device when
-   * it was attached to the channel.
-   * \return Returns true if the net device is attached to the
-   * channel, false otherwise.
-   */
-  bool IsActive(uint32_t deviceId);
-  /**
-   * \return Returns the number of net devices that are currently
-   * attached to the channel.
-   */
-  uint32_t GetNumActDevices (void);
-  /**
-   * \return Returns the total number of devices including devices
-   * that have been detached from the channel.
-   */
-  virtual uint32_t GetNDevices (void) const;
-  /**
-   * \param i The deviceId of the net device for which we want the
-   * pointer.
-   * \return Returns the pointer to the net device that is associated
-   * with deviceId i.
-   */
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
-
-  virtual DataRate GetDataRate (void);
-  virtual Time GetDelay (void);
-
-private:
-  DataRate      m_bps;    /// Data rate of the channel
-  Time          m_delay;  /// Delay of the channel.
-
-  /**
-   * List of the net devices that have been or are currently connected
-   * to the channel.
-   *
-   * Devices are nor removed from this list, they are marked as
-   * inactive. Otherwise the assigned device IDs will not refer to the
-   * correct NetDevice. The DeviceIds are used so that it is possible
-   * to have a number to refer to an entry in the list so that the
-   * whole list does not have to be searched when making sure that a
-   * source is attached to a channel when it is transmitting data.
-   */
-  std::vector< CsmaCdDeviceRec >            m_deviceList;
-  /**
-   * Packet that is currently being transmitted on the channel (or last
-   * packet to have been transmitted on the channel if the channel is
-   * free.)
-   */
-  Packet                              m_currentPkt;
-  /**
-   * Device Id of the source that is currently transmitting on the
-   * channel. Or last source to have transmitted a packet on the
-   * channel, if the channel is currently not busy.
-   */
-  uint32_t                            m_currentSrc;
-  /**
-   * Current state of the channel
-   */
-  WireState          m_state;
-  /**
-   * Initializes the channel when it is constructed. Resets the
-   * deviceList and sets the channel state to IDLE.
-   */
-  void Init (void);
-};
-
-} // namespace ns3
-
-#endif /* CSMA_CD_CHANNEL_H */
--- a/src/devices/csma-cd/csma-cd-ipv4-topology.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,156 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2007 Emmanuelle Laprise
-//
-// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
-//
-
-#include <algorithm>
-#include "ns3/assert.h"
-#include "ns3/debug.h"
-#include "ns3/fatal-error.h"
-#include "ns3/nstime.h"
-#include "ns3/internet-node.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4.h"
-#include "ns3/queue.h"
-
-#include "csma-cd-channel.h"
-#include "csma-cd-net-device.h"
-#include "csma-cd-ipv4-topology.h"
-
-namespace ns3 {
-
-
-uint32_t
-CsmaCdIpv4Topology::AddIpv4CsmaCdNode(Ptr<Node> n1,
-                                      Ptr<CsmaCdChannel> ch,
-                                      MacAddress addr)
-{
-  Ptr<Queue> q = Queue::CreateDefault ();
-
-  // assume full-duplex
-  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr, 
-                                                      ns3::CsmaCdNetDevice::IP_ARP,
-                                                      true, true);
-  nd0->AddQueue(q);
-  nd0->Attach (ch);
-  return nd0->GetIfIndex ();
-}
-
-
-void
-CsmaCdIpv4Topology::AddIpv4LlcCsmaCdNode(Ptr<Node> n1,
-                                         Ptr<CsmaCdChannel> ch,
-                                         MacAddress addr)
-{
-  Ptr<Queue> q = Queue::CreateDefault ();
-
-  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr,
-                                                      ns3::CsmaCdNetDevice::LLC,
-                                                      true, false);
-  nd0->AddQueue(q);
-  nd0->Attach (ch);
-
-  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr,
-                                                      ns3::CsmaCdNetDevice::LLC,
-                                                      false, true);
-  nd1->AddQueue(q);
-  nd1->Attach (ch);
-}
-
-void
-CsmaCdIpv4Topology::AddIpv4RawCsmaCdNode(Ptr<Node> n1,
-                                         Ptr<CsmaCdChannel> ch,
-                                         MacAddress addr)
-{
-  Ptr<Queue> q = Queue::CreateDefault ();
-
-  Ptr<CsmaCdNetDevice> nd0 = Create<CsmaCdNetDevice> (n1, addr,
-                                                      ns3::CsmaCdNetDevice::RAW,
-                                                      true, false);
-  nd0->AddQueue(q);
-  nd0->Attach (ch);
-
-  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr,
-                                                      ns3::CsmaCdNetDevice::RAW,
-                                                      false, true);
-  nd1->AddQueue(q);
-  nd1->Attach (ch);
-}
-
-void
-CsmaCdIpv4Topology::AddIpv4Address(Ptr<Node> n1,
-                                       int ndNum,
-                                       const Ipv4Address& addr1,
-                                       const Ipv4Mask& netmask1)
-{
-
-  // Duplex link is assumed to be subnetted as a /30
-  // May run this unnumbered in the future?
-  Ipv4Mask netmask(netmask1);
-
-  Ptr<NetDevice> nd1 = n1->GetDevice(ndNum);
-
-  Ptr<Ipv4> ip1 = n1->QueryInterface<Ipv4> (Ipv4::iid);
-  uint32_t index1 = ip1->AddInterface (nd1);
-
-  ip1->SetAddress (index1, addr1);
-  ip1->SetNetworkMask (index1, netmask);
-  ip1->SetUp (index1);
-
-}
-
-void
-CsmaCdIpv4Topology::AddIpv4Routes (
-  Ptr<NetDevice> nd1, Ptr<NetDevice> nd2)
-{ 
-  // Assert that both are Ipv4 nodes
-  Ptr<Ipv4> ip1 = nd1->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
-  Ptr<Ipv4> ip2 = nd2->GetNode ()->QueryInterface<Ipv4> (Ipv4::iid);
-  NS_ASSERT(ip1 != 0 && ip2 != 0);
-
-  // Get interface indexes for both nodes corresponding to the right channel
-  uint32_t index1 = 0;
-  bool found = false;
-  for (uint32_t i = 0; i < ip1->GetNInterfaces (); i++)
-    {
-      if (ip1 ->GetNetDevice (i) == nd1)
-        {
-          index1 = i;
-          found = true;
-        }
-    }
-  NS_ASSERT(found);
-
-  uint32_t index2 = 0;
-  found = false;
-  for (uint32_t i = 0; i < ip2->GetNInterfaces (); i++)
-    {
-      if (ip2 ->GetNetDevice (i) == nd2)
-        {
-          index2 = i;
-          found = true;
-        }
-    }
-  NS_ASSERT(found);
-
-  ip1->AddHostRouteTo (ip2-> GetAddress (index2), index1);
-  ip2->AddHostRouteTo (ip1-> GetAddress (index1), index2); 
-}
-
-} // namespace ns3
- 
--- a/src/devices/csma-cd/csma-cd-ipv4-topology.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2007 Emmanuelle Laprise
-//
-// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
-//
-
-#ifndef __CSMA_CD_IPV4_TOPOLOGY_H__
-#define __CSMA_CD_IPV4_TOPOLOGY_H__
-
-#include "ns3/ptr.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/ipv4.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/internet-node.h"
-#include "ns3/csma-cd-net-device.h"
-
-// The topology class consists of only static methods thar are used to
-// create the topology and data flows for an ns3 simulation
-
-namespace ns3 {
-
-class CsmaCdIpv4Channel;
-class Node;
-class IPAddr;
-class DataRate;
-class Queue;
-
-/**
- * \brief A helper class to create Topologies based on the
- * InternetNodes and CsmaCdChannels. Either the
- * SimpleCsmaCdNetDevice or the LLCCsmaCdNetDevice can be used
- * when constructing these topologies.
- */
-class CsmaCdIpv4Topology {
-public:
-
-  /**
-   * \param n1 Node to be attached to the Csma/Cd channel
-   * \param ch CsmaCdChannel to which node n1 should be attached
-   * \param addr Mac address of the node
-   *
-   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
-   * a EthernetCsmaCdNetDevice to the nodes so that they can
-   * connect to a CsmaCdChannel. This means that Ethernet headers
-   * and trailers will be added to the packet before sending out on
-   * the net device.
-   * 
-   * \return ifIndex of the device
-   */
-  static uint32_t AddIpv4CsmaCdNode( Ptr<Node> n1,
-                                 Ptr<CsmaCdChannel> ch,
-                                 MacAddress addr);
-
-  /**
-   * \param n1 Node to be attached to the Csma/Cd channel
-   * \param ch CsmaCdChannel to which node n1 should be attached
-   * \param addr Mac address of the node
-   *
-   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
-   * a RawCsmaCdNetDevice to the nodes so that they can connect
-   * to a CsmaCdChannel.
-   */
-  static void AddIpv4RawCsmaCdNode( Ptr<Node> n1,
-                                    Ptr<CsmaCdChannel> ch,
-                                    MacAddress addr);
-
-  /**
-   * \param n1 Node to be attached to the Csma/Cd channel
-   * \param ch CsmaCdChannel to which node n1 should be attached
-   * \param addr Mac address of the node
-   *
-   * Add a Csma/Cd node to a Csma/Cd channel. This function adds
-   * a LlcCsmaCdNetDevice to the nodes so that they can connect
-   * to a CsmaCdChannel.
-   */
-  static void AddIpv4LlcCsmaCdNode( Ptr<Node> n1,
-                                    Ptr<CsmaCdChannel> ch,
-                                    MacAddress addr);
-
-
-
-  /** 
-   * \param n1 Node
-   * \param ndNum NetDevice number with which to associate address
-   * \param addr1 Ipv4 Address for ndNum of n1
-   * \param network network mask for ndNum of node n1
-   * 
-   * Add an Ipv4Address to the Ipv4 interface associated with the
-   * ndNum CsmaCdIpv4NetDevices on the provided
-   * CsmaCdIpv4Channel
-   */
-  static void AddIpv4Address(Ptr<Node> n1, int ndNum, 
-                             const Ipv4Address& addr1,
-                             const Ipv4Mask& netmask1);
-
-  /**
-   * \param nd1 Node
-   * \param nd2 Node
-   * 
-   * Add an IPV4 host route between the two specified net devices
-   */
-  static void AddIpv4Routes (Ptr<NetDevice> nd1, Ptr<NetDevice> nd2);
-};
-
-} // namespace ns3
-
-#endif
-
--- a/src/devices/csma-cd/csma-cd-net-device.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,488 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Emmanuelle Laprise
- * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
- */
-
-#include <iostream>
-#include <cassert>
-#include "ns3/debug.h"
-#include "ns3/queue.h"
-#include "ns3/simulator.h"
-#include "ns3/composite-trace-resolver.h"
-#include "csma-cd-net-device.h"
-#include "csma-cd-channel.h"
-#include "ns3/ethernet-header.h"
-#include "ns3/ethernet-trailer.h"
-#include "ns3/llc-snap-header.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("CsmaCdNetDevice");
-
-namespace ns3 {
-
-CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
-                                  CsmaCdEncapsulationMode encapMode) 
-  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
-{
-  NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
-  m_encapMode = encapMode;
-
-  Init(true, true);
-}
-
-CsmaCdNetDevice::CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, 
-                                  CsmaCdEncapsulationMode encapMode,
-                                  bool sendEnable, bool receiveEnable) 
-  : NetDevice(node, addr), m_bps (DataRate (0xffffffff))
-{
-  NS_DEBUG ("CsmaCdNetDevice::CsmaCdNetDevice (" << node << ")");
-  m_encapMode = encapMode;
-
-  Init(sendEnable, receiveEnable);
-}
-
-CsmaCdNetDevice::~CsmaCdNetDevice()
-{
-  NS_DEBUG ("CsmaCdNetDevice::~CsmaCdNetDevice ()");
-  m_queue = 0;
-}
-
-void 
-CsmaCdNetDevice::DoDispose ()
-{
-  m_channel = 0;
-  NetDevice::DoDispose ();
-}
-
-//
-// Assignment operator for CsmaCdNetDevice.
-//
-// This uses the non-obvious trick of taking the source net device passed by
-// value instead of by reference.  This causes the copy constructor to be
-// invoked (where the real work is done -- see above).  All we have to do
-// here is to return the newly constructed net device.
-//
-/*
-CsmaCdNetDevice&
-CsmaCdNetDevice::operator= (const CsmaCdNetDevice nd)
-{
-  NS_DEBUG ("CsmaCdNetDevice::operator= (" << &nd << ")");
-  return *this;
-}
-*/
-
-void 
-CsmaCdNetDevice::Init(bool sendEnable, bool receiveEnable)
-{
-  m_txMachineState = READY;
-  m_tInterframeGap = Seconds(0);
-  m_channel = 0; 
-  m_queue = 0;
-
-  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
-  EnableMulticast();
-  EnablePointToPoint();
-
-  SetSendEnable (sendEnable);
-  SetReceiveEnable (receiveEnable);
-}
-
-void
-CsmaCdNetDevice::SetSendEnable (bool sendEnable)
-{
-  m_sendEnable = sendEnable;
-}
-
-void
-CsmaCdNetDevice::SetReceiveEnable (bool receiveEnable)
-{
-  m_receiveEnable = receiveEnable;
-}
-bool
-CsmaCdNetDevice::IsSendEnabled (void)
-{
-  return (m_sendEnable);
-}
-
-bool
-CsmaCdNetDevice::IsReceiveEnabled (void)
-{
-  return (m_receiveEnable);
-}
-
-void 
-CsmaCdNetDevice::SetDataRate (DataRate bps)
-{
-  m_bps = bps;
-}
-
-void 
-CsmaCdNetDevice::SetInterframeGap (Time t)
-{
-  m_tInterframeGap = t;
-}
-
-void 
-CsmaCdNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, 
-                                      uint32_t maxSlots, uint32_t ceiling, 
-                                      uint32_t maxRetries)
-{
-  m_backoff.m_slotTime = slotTime;
-  m_backoff.m_minSlots = minSlots;
-  m_backoff.m_maxSlots = maxSlots;
-  m_backoff.m_ceiling = ceiling;
-  m_backoff.m_maxRetries = maxRetries;
-}
-void 
-CsmaCdNetDevice::AddHeader (Packet& p, const MacAddress& dest,
-                            uint16_t protocolNumber)
-{
-  if (m_encapMode == RAW)
-    {
-      return;
-    }
-  EthernetHeader header (false);
-  EthernetTrailer trailer;
-  header.SetSource(this->GetAddress());
-  header.SetDestination(dest);
-
-  uint16_t lengthType = 0;
-  switch (m_encapMode) 
-    {
-    case ETHERNET_V1:
-      lengthType = p.GetSize() + header.GetSize() + trailer.GetSize();
-      break;
-    case IP_ARP:
-      lengthType = protocolNumber;
-      break;
-    case LLC: {
-      LlcSnapHeader llc;
-      llc.SetType (protocolNumber);
-      p.AddHeader (llc);
-    } break;
-    case RAW:
-      NS_ASSERT (false);
-      break;
-    }
-  header.SetLengthType (lengthType);
-  p.AddHeader(header);
-  trailer.CalcFcs(p);
-  p.AddTrailer(trailer);
-}
-bool 
-CsmaCdNetDevice::ProcessHeader (Packet& p, uint16_t & param)
-{
-  if (m_encapMode == RAW)
-    {
-      return true;
-    }
-  EthernetHeader header (false);
-  EthernetTrailer trailer;
-      
-  p.RemoveTrailer(trailer);
-  trailer.CheckFcs(p);
-  p.RemoveHeader(header);
-
-  if ((header.GetDestination() != this->GetBroadcast()) &&
-      (header.GetDestination() != this->GetAddress()))
-    {
-      return false;
-    }
-
-  switch (m_encapMode)
-    {
-    case ETHERNET_V1:
-    case IP_ARP:
-      param = header.GetLengthType();
-      break;
-    case LLC: {
-      LlcSnapHeader llc;
-      p.RemoveHeader (llc);
-      param = llc.GetType ();
-    } break;
-    case RAW:
-      NS_ASSERT (false);
-      break;
-    }
-  return true;
-}
-
-bool
-CsmaCdNetDevice::DoNeedsArp (void) const
-{
-  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-bool
-CsmaCdNetDevice::SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber)
-{
-  NS_DEBUG ("CsmaCdNetDevice::SendTo (" << &p << ")");
-  NS_DEBUG ("CsmaCdNetDevice::SendTo (): UID is " << p.GetUid () << ")");
-
-  NS_ASSERT (IsLinkUp ());
-
-  // Only transmit if send side of net device is enabled
-  if (!IsSendEnabled())
-    return false;
-
-  AddHeader(p, dest, protocolNumber);
-
-  // Place the packet to be sent on the send queue
-  if (m_queue->Enqueue(p) == false )
-    {
-      return false;
-    }
-  // If the device is idle, we need to start a transmission. Otherwise,
-  // the transmission will be started when the current packet finished
-  // transmission (see TransmitCompleteEvent)
-  if (m_txMachineState == READY) 
-    {
-      // Store the next packet to be transmitted
-      if (m_queue->Dequeue (m_currentPkt))
-        {
-          TransmitStart();
-        }
-    }
-  return true;
-}
-
-void
-CsmaCdNetDevice::TransmitStart ()
-{
-  NS_DEBUG ("CsmaCdNetDevice::TransmitStart (" << &m_currentPkt << ")");
-  NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): UID is " 
-            << m_currentPkt.GetUid () << ")");
-//
-// This function is called to start the process of transmitting a packet.
-// We need to tell the channel that we've started wiggling the wire and
-// schedule an event that will be executed when it's time to tell the 
-// channel that we're done wiggling the wire.
-//
-  NS_ASSERT_MSG((m_txMachineState == READY) || (m_txMachineState == BACKOFF), 
-                "Must be READY to transmit. Tx state is: " 
-                << m_txMachineState);
-
-  // Only transmit if send side of net device is enabled
-  if (!IsSendEnabled())
-    return;
-
-  if (m_channel->GetState() != IDLE)
-    { // Channel busy, backoff and rechedule TransmitStart()
-      m_txMachineState = BACKOFF;
-      if (m_backoff.MaxRetriesReached())
-        { // Too many retries reached, abort transmission of packet
-          TransmitAbort();
-        } 
-      else 
-        {
-          m_backoff.IncrNumRetries();
-          Time backoffTime = m_backoff.GetBackoffTime();
-
-          NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " 
-                    << "Channel busy, backing off for " 
-                    << backoffTime.GetSeconds () << "sec");
-
-          Simulator::Schedule (backoffTime, 
-                               &CsmaCdNetDevice::TransmitStart, 
-                               this);
-        }
-    } 
-  else 
-    {
-      // Channel is free, transmit packet
-      m_txMachineState = BUSY;
-      Time tEvent = Seconds (m_bps.CalculateTxTime(m_currentPkt.GetSize()));
-      
-      NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " <<
-                "Schedule TransmitCompleteEvent in " << 
-                tEvent.GetSeconds () << "sec");
-      
-      Simulator::Schedule (tEvent, 
-                           &CsmaCdNetDevice::TransmitCompleteEvent, 
-                           this);
-      if (!m_channel->TransmitStart (m_currentPkt, m_deviceId))
-        {
-          NS_DEBUG ("CsmaCdNetDevice::TransmitStart (): " <<
-                    "Channel transmit start did not work at " << 
-                    tEvent.GetSeconds () << "sec");
-          m_txMachineState = READY;
-        } 
-      else 
-        {
-          // Transmission success, reset backoff time parameters.
-          m_backoff.ResetBackoffTime();
-        }
-    }
-}
-
-
-void
-CsmaCdNetDevice::TransmitAbort (void)
-{
-  NS_DEBUG ("CsmaCdNetDevice::TransmitAbort ()");
-
-  NS_DEBUG ("CsmaCdNetDevice::TransmitAbort (): Pkt UID is " <<
-            m_currentPkt.GetUid () << ")");
-
-  // Try to transmit a new packet
-  bool found;
-  found = m_queue->Dequeue (m_currentPkt);
-  NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
-  m_backoff.ResetBackoffTime();
-  m_txMachineState = READY;
-  TransmitStart ();
-}
-
-void
-CsmaCdNetDevice::TransmitCompleteEvent (void)
-{
-  NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent ()");
-//
-// This function is called to finish the  process of transmitting a packet.
-// We need to tell the channel that we've stopped wiggling the wire and
-// schedule an event that will be executed when it's time to re-enable
-// the transmitter after the interframe gap.
-//
-  NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
-  // Channel should be transmitting
-  NS_ASSERT(m_channel->GetState() == TRANSMITTING);
-  m_txMachineState = GAP;
-
-  NS_DEBUG ("CsmaCdNetDevice::TransmitCompleteEvent (): Pkt UID is " << 
-            m_currentPkt.GetUid () << ")");
-  m_channel->TransmitEnd (); 
-
-  NS_DEBUG (
-    "CsmaCdNetDevice::TransmitCompleteEvent (): " <<
-    "Schedule TransmitReadyEvent in "
-    << m_tInterframeGap.GetSeconds () << "sec");
-
-  Simulator::Schedule (m_tInterframeGap, 
-                       &CsmaCdNetDevice::TransmitReadyEvent, 
-                       this);
-}
-
-void
-CsmaCdNetDevice::TransmitReadyEvent (void)
-{
-  NS_DEBUG ("CsmaCdNetDevice::TransmitReadyEvent ()");
-//
-// This function is called to enable the transmitter after the interframe
-// gap has passed.  If there are pending transmissions, we use this opportunity
-// to start the next transmit.
-//
-  NS_ASSERT_MSG(m_txMachineState == GAP, "Must be in interframe gap");
-  m_txMachineState = READY;
-
-  // Get the next packet from the queue for transmitting
-  if (m_queue->IsEmpty())
-    {
-      return;
-    }
-  else
-    {
-      bool found;
-      found = m_queue->Dequeue (m_currentPkt);
-      NS_ASSERT_MSG(found, "IsEmpty false but no Packet on queue?");
-      TransmitStart ();
-    }
-}
-
-TraceResolver *
-CsmaCdNetDevice::DoCreateTraceResolver (TraceContext const &context)
-{
-  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
-  resolver->Add ("queue", 
-                 MakeCallback (&Queue::CreateTraceResolver, 
-                               PeekPointer (m_queue)),
-                 CsmaCdNetDevice::QUEUE);
-  resolver->Add ("rx",
-                 m_rxTrace,
-                 CsmaCdNetDevice::RX);
-  return resolver;
-}
-
-bool
-CsmaCdNetDevice::Attach (Ptr<CsmaCdChannel> ch)
-{
-  NS_DEBUG ("CsmaCdNetDevice::Attach (" << &ch << ")");
-
-  m_channel = ch;
-
-  m_deviceId = m_channel->Attach(this);
-  m_bps = m_channel->GetDataRate ();
-  m_tInterframeGap = m_channel->GetDelay ();
-
-  /* 
-   * For now, this device is up whenever a channel is attached to it.
-   */
-  NotifyLinkUp ();
-  return true;
-}
-
-void
-CsmaCdNetDevice::AddQueue (Ptr<Queue> q)
-{
-  NS_DEBUG ("CsmaCdNetDevice::AddQueue (" << q << ")");
-
-  m_queue = q;
-}
-
-void
-CsmaCdNetDevice::Receive (Packet& p)
-{
-  NS_DEBUG ("CsmaCdNetDevice::Receive UID is (" << p.GetUid() << ")");
-
-  // Only receive if send side of net device is enabled
-  if (!IsReceiveEnabled())
-    return;
-
-  uint16_t param = 0;
-  Packet packet = p;
-
-  if (ProcessHeader(packet, param))
-    {
-      m_rxTrace (packet);
-      ForwardUp (packet, param);
-    } 
-  else 
-    {
-      m_dropTrace (packet);
-    }
-}
-
-Ptr<Queue>
-CsmaCdNetDevice::GetQueue(void) const 
-{ 
-    return m_queue;
-}
-
-Ptr<Channel>
-CsmaCdNetDevice::DoGetChannel(void) const 
-{ 
-    return m_channel;
-}
-
-} // namespace ns3
--- a/src/devices/csma-cd/csma-cd-net-device.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,409 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 Emmanuelle Laprise
- *
- * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca
- * Derived from the p2p net device file
- */
-
-#ifndef CSMA_CD_NET_DEVICE_H
-#define CSMA_CD_NET_DEVICE_H
-
-#include <string.h>
-#include "ns3/node.h"
-#include "ns3/backoff.h"
-#include "ns3/mac-address.h"
-#include "ns3/net-device.h"
-#include "ns3/callback.h"
-#include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
-#include "ns3/nstime.h"
-#include "ns3/data-rate.h"
-#include "ns3/ptr.h"
-#include "ns3/random-variable.h"
-
-namespace ns3 {
-
-class Queue;
-class CsmaCdChannel;
-
-/**
- * \class CsmaCdNetDevice
- * \brief A Device for a CsmaCd Network Link.
- *
- * The Csma/Cd net device class is analogous to layer 1 and 2 of the
- * TCP stack. The NetDevice takes a raw packet of bytes and creates a
- * protocol specific packet from them. The Csma/Cd net device class
- * takes this packet and adds and processes the headers/trailers that
- * are associated with EthernetV1, EthernetV2, RAW or LLC
- * protocols. The EthernetV1 packet type adds and removes Ethernet
- * destination and source addresses. The LLC packet type adds and
- * removes LLC snap headers. The raw packet type does not add or
- * remove any headers.  Each Csma/Cd net device will receive all
- * packets written to the Csma/Cd link. The ProcessHeader function can
- * be used to filter out the packets such that higher level layers
- * only receive packets that are addressed to their associated net
- * devices
- *
- */
-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.
-   *
-   */
-enum CsmaCdEncapsulationMode {
-  ETHERNET_V1, /**< Version one ethernet packet, length field */
-  IP_ARP,      /**< Ethernet packet encapsulates IP/ARP packet */
-  RAW,         /**< Packet that contains no headers */
-  LLC,         /**< LLC packet encapsulation */  
-};
-
-  /**
-   * Construct a CsmaCdNetDevice
-   *
-   * This is the constructor for the CsmaCdNetDevice.  It takes as a
-   * parameter the Node to which this device is connected.  Ownership of the
-   * Node pointer is not implied and the node must not be deleted.
-   *
-   * \param node the Node to which this device is connected.
-   * \param addr The source MAC address of the net device.
-   */
-  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr, CsmaCdEncapsulationMode pktType);
-  CsmaCdNetDevice (Ptr<Node> node, MacAddress addr,
-                   CsmaCdEncapsulationMode pktType,
-                   bool sendEnable, bool receiveEnable);
-  /**
-   * Destroy a CsmaCdNetDevice
-   *
-   * This is the destructor for the CsmaCdNetDevice.
-   */
-  virtual ~CsmaCdNetDevice();
-  /**
-   * Set the Data Rate used for transmission of packets.  The data rate is
-   * set in the Attach () method from the corresponding field in the channel
-   * to which the device is attached.  It can be overridden using this method.
-   *
-   * @see Attach ()
-   * \param bps the data rate at which this object operates
-   */
-  void SetDataRate (DataRate bps);
-  /**
-   * Set the inteframe gap used to separate packets.  The interframe gap
-   * defines the minimum space required between packets sent by this device.
-   * It is usually set in the Attach () method based on the speed of light
-   * delay of the channel to which the device is attached.  It can be 
-   * overridden using this method if desired.
-   *
-   * @see Attach ()
-   * \param t the interframe gap time
-   */
-  void SetInterframeGap (Time t);
-  /**
-   * Set the backoff parameters used to determine the wait to retry
-   * transmitting a packet when the channel is busy.
-   *
-   * @see Attach ()
-   * \param slotTime Length of a packet slot (or average packet time)
-   * \param minSlots Minimum number of slots to wait
-   * \param maxSlots Maximum number of slots to wait
-   * \param maxRetries Maximum number of retries before packet is discard
-   * \param ceiling Cap on the exponential function when calculating max slots
-   */
-  void SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, 
-                        uint32_t maxRetries, uint32_t ceiling);
-  /**
-   * Attach the device to a channel.
-   *
-   * The function Attach is used to add a CsmaCdNetDevice to a
-   * CsmaCdChannel.
-   *
-   * @see SetDataRate ()
-   * @see SetInterframeGap ()
-   * \param ch a pointer to the channel to which this object is being attached.
-   */
-  bool Attach (Ptr<CsmaCdChannel> ch);
-  /**
-   * Attach a queue to the CsmaCdNetDevice.
-   *
-   * The CsmaCdNetDevice "owns" a queue.  This queue is created by the
-   * CsmaCdTopology object and implements a queueing method such as
-   * DropTail or RED.  The CsmaCdNetDevice assumes ownership of this
-   * queue and must delete it when the device is destroyed.
-   *
-   * @see CsmaCdTopology::AddCsmaCdLink ()
-   * @see Queue
-   * @see DropTailQueue
-   * \param queue a pointer to the queue for which object is assuming
-   *        ownership.
-   */
-  void AddQueue (Ptr<Queue> queue);
-  /**
-   * Receive a packet from a connected CsmaCdChannel.
-   *
-   * The CsmaCdNetDevice receives packets from its connected channel
-   * and forwards them up the protocol stack.  This is the public method
-   * used by the channel to indicate that the last bit of a packet has 
-   * arrived at the device.
-   *
-   * @see CsmaCdChannel
-   * \param p a reference to the received packet
-   */
-  void Receive (Packet& p);
-
-  bool IsSendEnabled (void);
-  bool IsReceiveEnabled (void);
-
-  void SetSendEnable (bool);
-  void SetReceiveEnable (bool);
-
-protected:
-  virtual bool DoNeedsArp (void) const;
-  virtual void DoDispose (void);
-  /**
-   * Get a copy of the attached Queue.
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the underlying queue.
-   *
-   * \return a pointer to the queue.
-   */
-  Ptr<Queue> GetQueue (void) const; 
-  /**
-   * Get a copy of the attached Channel
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the connected channel
-   *
-   * \return a pointer to the channel
-   */
-  virtual Ptr<Channel> DoGetChannel (void) const;
-  /**
-   * Adds the necessary headers and trailers to a packet of data in order to
-   * respect the packet type
-   *
-   * \param p Packet to which header should be added
-   * \param dest MAC destination address to which packet should be sent
-   * \param protocolNumber In some protocols, identifies the type of
-   * payload contained in this packet.
-   */
-  void AddHeader (Packet& p, const MacAddress& dest, 
-                  uint16_t protocolNumber);
-  /**
-   * Removes, from a packet of data, all headers and trailers that
-   * relate to the packet type
-   *
-   * \param p Packet whose headers need to be processed
-   * \param param An integer parameter that can be set by the function
-   * to return information gathered in the header
-   * \return Returns true if the packet should be forwarded up the
-   * protocol stack.
-   */
-  bool ProcessHeader (Packet& p, uint16_t & param);
-
-private:
-  // disable copy constructor and operator =
-  CsmaCdNetDevice &operator = (const CsmaCdNetDevice &o);
-  CsmaCdNetDevice (const CsmaCdNetDevice &o);
-  /**
-   * Initializes variablea when construction object.
-   */
-  void Init (bool sendEnable, bool receiveEnable);
-  /**
-   * Send a Packet on the Csma/Cd network
-   *
-   * This method does not use a destination address since all packets
-   * are broadcast to all NetDevices attached to the channel. Packet
-   * should contain all needed headers at this time.
-   *
-   * If the device is ready to transmit, the next packet is read off
-   * of the queue and stored locally until it has been transmitted.
-   *
-   * \param p a reference to the packet to send
-   * \param dest destination address
-   * \param protocolNumber -- this parameter is not used here
-   * \return true if success, false on failure
-   */
-  virtual bool SendTo (Packet& p, const MacAddress& dest, uint16_t protocolNumber);
-
-  /**
-   * Start Sending a Packet Down the Wire.
-   *
-   * The TransmitStart method is the method that is used internally in
-   * the CsmaCdNetDevice to begin the process of sending a packet
-   * out on the channel.  The corresponding method is called on the
-   * channel to let it know that the physical device this class
-   * represents has virually started sending signals, this causes the
-   * channel to become busy.  An event is scheduled for the time at
-   * which the bits have been completely transmitted. If the channel
-   * is busy, the method reschedules itself for a later time (within
-   * the backoff period)
-   *
-   * @see CsmaCdChannel::TransmitStart ()
-   * @see TransmitCompleteEvent ()
-   */
-  void TransmitStart ();
-  /**
-   * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
-   *
-   * The TransmitCompleteEvent method is used internally to finish the process
-   * of sending a packet out on the channel.  During execution of this method
-   * the TransmitEnd method is called on the channel to let it know that the
-   * physical device this class represents has virually finished sending 
-   * signals.  The channel uses this event to begin its speed of light delay
-   * timer after which it notifies the Net Device at the other end of the 
-   * link that the bits have arrived.  During this method, the net device 
-   * also schedules the TransmitReadyEvent at which time the transmitter 
-   * becomes ready to send the next packet.
-   *
-   * @see CsmaCdChannel::TransmitEnd ()
-   * @see TransmitReadyEvent ()
-   */
-  void TransmitCompleteEvent (void);
-  /**
-   * Cause the Transmitter to Become Ready to Send Another Packet.
-   *
-   * The TransmitReadyEvent method is used internally to re-enable the 
-   * transmit machine of the net device.  It is scheduled after a suitable
-   * interframe gap after the completion of the previous transmission.
-   * The queue is checked at this time, and if there is a packet waiting on
-   * the queue, the transmission process is begun.
-   *
-   * If a packet is in the queue, it is extracted for the queue as the
-   * next packet to be transmitted by the net device.
-   *
-   * @see TransmitStart ()
-   */
-  void TransmitReadyEvent (void);
-  /**
-   * Create a Trace Resolver for events in the net device.
-   * (NOT TESTED)
-   * @see class TraceResolver
-   */
-  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
-
-  /**
-   * Aborts the transmission of the current packet
-   *
-   * If the net device has tried to transmit a packet for more times
-   * than the maximum allowed number of retries (channel always busy)
-   * then the packet is dropped.
-   *
-   */
-  void TransmitAbort (void);
-
-  /** 
-   * Device ID returned by the attached functions. It is used by the
-   * mp-channel to identify each net device to make sure that only
-   * active net devices are writing to the channel
-   */
-  uint32_t m_deviceId; 
-
-  /**
-   * Enable net device to send packets. True by default
-   */
-  bool m_sendEnable;
-  /**
-   * Enable net device to receive packets. True by default
-   */
-  bool m_receiveEnable;
-  /**
-   * Enumeration of the states of the transmit machine of the net device.
-   */
-  enum TxMachineState
-    {
-      READY, /**< The transmitter is ready to begin transmission of a packet */
-      BUSY,  /**< The transmitter is busy transmitting a packet */
-      GAP,    /**< The transmitter is in the interframe gap time */
-      BACKOFF    /**< The transmitter is waiting for the channel to be free */
-    };
-  /**
-   * The state of the Net Device transmit state machine.
-   * @see TxMachineState
-   */
-  TxMachineState m_txMachineState;
-  
-  /**
-   * The type of packet that should be created by the AddHeader
-   * function and that should be processed by the ProcessHeader
-   * function.
-   */
-  CsmaCdEncapsulationMode m_encapMode;
-  /**
-   * The data rate that the Net Device uses to simulate packet transmission
-   * timing.
-   * @see class DataRate
-   */
-  DataRate m_bps;
-  /**
-   * The interframe gap that the Net Device uses to throttle packet
-   * transmission
-   * @see class Time
-   */
-  Time m_tInterframeGap;
-  /**
-   * Holds the backoff parameters and is used to calculate the next
-   * backoff time to use when the channel is busy and the net device
-   * is ready to transmit
-   */
-  Backoff m_backoff;
-  /**
-   * Next packet that will be transmitted (if transmitter is not
-   * currently transmitting) or packet that is currently being
-   * transmitted.
-   */
-  Packet m_currentPkt;
-  /**
-   * The CsmaCdChannel to which this CsmaCdNetDevice has been
-   * attached.
-   * @see class CsmaCdChannel
-   */
-  Ptr<CsmaCdChannel> m_channel;
-  /**
-   * The Queue which this CsmaCdNetDevice uses as a packet source.
-   * Management of this Queue has been delegated to the CsmaCdNetDevice
-   * and it has the responsibility for deletion.
-   * @see class Queue
-   * @see class DropTailQueue
-   */
-  Ptr<Queue> m_queue;
-  /**
-   * NOT TESTED
-   * The trace source for the packet reception events that the device can
-   * fire.
-   *
-   * @see class CallBackTraceSource
-   * @see class TraceResolver
-   */
-  CallbackTraceSource<Packet &> m_rxTrace;
-  CallbackTraceSource<Packet &> m_dropTrace;
-
-};
-
-}; // namespace ns3
-
-#endif // CSMA_CD_NET_DEVICE_H
-
--- a/src/devices/csma-cd/csma-cd-topology.cc	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2007 Emmanuelle Laprise
-//
-// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
-//
-
-//
-// Topology helper for CsmaCd channels in ns3.
-
-#include "ns3/assert.h"
-#include "ns3/debug.h"
-#include "ns3/queue.h"
-
-#include "csma-cd-channel.h"
-#include "csma-cd-net-device.h"
-#include "csma-cd-topology.h"
-#include "ns3/socket-factory.h"
-
-namespace ns3 {
-
-Ptr<CsmaCdChannel>
-CsmaCdTopology::CreateCsmaCdChannel(
-  const DataRate& bps,
-  const Time& delay)
-{
-  Ptr<CsmaCdChannel> channel = Create<CsmaCdChannel> (bps, delay);
-
-  return channel;
-}
-
-#if 0
-Ptr<CsmaCdNetDevice>
-CsmaCdTopology::AddCsmaCdEthernetNode(
-  Ptr<Node> n1,
-  Ptr<CsmaCdChannel> ch,
-  MacAddress addr)
-{
-  Ptr<CsmaCdNetDevice> nd1 = Create<CsmaCdNetDevice> (n1, addr, 
-                                                      ns3::CsmaCdNetDevice::ETHERNET_V1);
-
-  Ptr<Queue> q = Queue::CreateDefault ();
-  nd1->AddQueue(q);
-  nd1->Attach (ch);
-  
-  return nd1;
-}
-
-Ptr<PacketSocket>
-CsmaCdTopology::ConnectPacketSocket(Ptr<PacketSocketApp> app, 
-                                        Ptr<CsmaCdNetDevice> ndSrc,
-                                        Ptr<CsmaCdNetDevice> ndDest)
-{
-  Ptr<PacketSocket> socket = Create<PacketSocket> ();
-  socket->Bind(ndSrc);
-  socket->Connect(ndDest->GetAddress());
-  app->Connect(socket);
-
-  return socket;
-}
-
-Ptr<PacketSocket>
-CsmaCdTopology::ConnectPacketSocket(Ptr<PacketSocketApp> app,
-                                        Ptr<CsmaCdNetDevice> ndSrc,
-                                        MacAddress macAddr)
-{
-  Ptr<PacketSocket> socket = Create<PacketSocket> ();
-  socket->Bind(ndSrc);
-  socket->Connect(macAddr);
-  app->Connect(socket);
-
-  return socket;
-}
-
-Ptr<Socket>
-CsmaCdTopology::CreatePacketSocket(Ptr<Node> n1, std::string iid_name)
-{
-  InterfaceId iid = InterfaceId::LookupByName (iid_name);
-
-  Ptr<SocketFactory> socketFactory =
-    n1->QueryInterface<SocketFactory> (iid);
-
-  Ptr<Socket> socket = socketFactory->CreateSocket ();
-
-  return socket;
-}
-#endif
-
-} // namespace ns3
- 
--- a/src/devices/csma-cd/csma-cd-topology.h	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,128 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2007 Emmanuelle Laprise
-//
-// 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
-//
-// Topology helper for multipoint channels in ns3.
-// 
-#ifndef CSMA_CD_TOPOLOGY_H
-#define CSMA_CD_TOPOLOGY_H
-
-#include "ns3/ptr.h"
-#include "ns3/csma-cd-net-device.h"
-#if 0
-#include "ns3/packet-socket.h"
-#include "ns3/packet-socket-app.h"
-#endif
-#include "ns3/node.h"
-#include "ns3/mac-address.h"
-
-// The topology class consists of only static methods thar are used to
-// create the topology and data flows for an ns3 simulation
-
-namespace ns3 {
-
-class CsmaCdChannel;
-class Node;
-class DataRate;
-class Queue;
-
-/**
- * \brief A helper class to create CsmaCd Topologies 
- *
- * CsmaCd topologies are created based on the
- * ns3::CsmaCdNetDevice subclasses and ns3::CsmaCdChannel
- * objects.  This class uses the EthernetNetDevice and
- * PacketSocket classes in order to create logical connections between
- * net devices. The PacketSocket class generates the data and the
- * EthernetNetDevice class creates ethernet packets from the
- * data, filling in source and destination addresses. The
- * EthernetNetDevice class filters received data packets
- * according to its destination Mac addresses.
- */
-class CsmaCdTopology {
-public:
-  /** 
-   * \param dataRate Maximum transmission link rate 
-   * \param delay propagation delay between any two nodes 
-   * \return Pointer to the created CsmaCdChannel
-   * 
-   * Create a CsmaCdChannel. All nodes connected to a multipoint
-   * channels will receive all packets written to that channel
-   */
-  static Ptr<CsmaCdChannel> CreateCsmaCdChannel(
-    const DataRate& dataRate, const Time& delay);
-
-#if 0
-  /**
-   * \param n1 Node to be attached to the multipoint channel
-   * \param ch CsmaCdChannel to which node n1 should be attached 
-   * \param addr MacAddress that should be assigned to the
-   * EthernetNetDevice that will be added to the node.
-   *
-   * Add a multipoint node to a multipoint channel
-   */
-  static Ptr<CsmaCdNetDevice> AddCsmaCdEthernetNode(Ptr<Node> n1, 
-                                                    Ptr<CsmaCdChannel> ch,
-                                                    MacAddress addr);
-
-  /**
-   * \param app Application that will be sending data to the agent
-   * \param ndSrc Net Device that will be sending the packets onto the
-   * network
-   * \param ndDest Net Device to which ndSrc will be sending the packets
-   * \return A pointer to the PacketSocket
-   *
-   * Creates an PacketSocket and configure it to send packets between
-   * two net devices
-   */
-static Ptr<PacketSocket> ConnectPacketSocket(Ptr<PacketSocketApp> app,
-                                      Ptr<CsmaCdNetDevice> ndSrc,
-                                      Ptr<CsmaCdNetDevice> ndDest);
-
-  /**
-   * \param app Application that will be sending data to the agent
-   * \param ndSrc Net Device that will be sending the packets onto the
-   * network 
-   * \param macAddr Mac destination address for the packets send by
-   * the ndSrc net device \return a Pointer to the created
-   * PacketSocket
-   *
-   * Creates an PacketSocket and configure it to send packets from a
-   * net device to a destination MacAddress
-   */
-static Ptr<PacketSocket> ConnectPacketSocket(Ptr<PacketSocketApp> app,
-                                      Ptr<CsmaCdNetDevice> ndSrc,
-                                      MacAddress macAddr);
-
-  /**
-   * \param n1 Node from which socketfactory should be tested.
-   * \param iid_name Interface identifier ("Packet", in this case)
-   *
-   * This is a test function to make sure that a socket can be created
-   * by using the socketfactory interface provided in the
-   * netdevicenode.
-   */
-static  Ptr<Socket> CreatePacketSocket(Ptr<Node> n1, 
-                                       std::string iid_name);
-#endif
-
-};
-} // namespace ns3
-
-#endif
-
--- a/src/devices/csma-cd/wscript	Mon Jul 30 14:48:56 2007 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-
-
-def build(bld):
-    obj = bld.create_obj('cpp', 'shlib')
-    obj.name = 'ns3-csma-cd'
-    obj.target = obj.name
-    obj.uselib_local = ['ns3-node']
-    obj.source = [
-        'backoff.cc',
-        'csma-cd-net-device.cc',
-        'csma-cd-channel.cc',
-        'csma-cd-topology.cc',
-        'csma-cd-ipv4-topology.cc',
-        ]
-    headers = bld.create_obj('ns3header')
-    headers.source = [
-        'backoff.h',
-        'csma-cd-net-device.h',
-        'csma-cd-channel.h',
-        'csma-cd-topology.h',
-        'csma-cd-ipv4-topology.h',
-        ]
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma/backoff.cc	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,83 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, Emmanuelle Laprise
+ * 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: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
+ */
+
+#include "backoff.h"
+
+namespace ns3 {
+
+Backoff::Backoff() 
+{
+  m_slotTime = MicroSeconds(1);
+  m_minSlots = 1;
+  m_maxSlots = 1000;
+  m_ceiling = 10;
+  m_maxRetries = 1000;
+
+  ResetBackoffTime();
+}
+
+Backoff::Backoff(Time slotTime, uint32_t minSlots, uint32_t maxSlots,
+                 uint32_t ceiling, uint32_t maxRetries)
+{
+  m_slotTime = slotTime;
+  m_minSlots = minSlots;
+  m_maxSlots = maxSlots;
+  m_ceiling = ceiling;
+  m_maxRetries = maxRetries;
+}  
+
+Time
+Backoff::GetBackoffTime (void)
+{
+  Time backoff;
+  uint32_t ceiling;
+
+  if ((m_ceiling > 0) &&(m_numBackoffRetries > m_ceiling))
+    ceiling = m_ceiling;
+  else
+    ceiling = m_numBackoffRetries;
+
+  uint32_t minSlot = m_minSlots;
+  uint32_t maxSlot = (uint32_t)pow(2, ceiling) - 1;
+  if (maxSlot > m_maxSlots)
+    maxSlot = m_maxSlots;
+
+  uint32_t backoffSlots = 
+    (uint32_t)UniformVariable::GetSingleValue(minSlot, maxSlot);
+
+  backoff = Scalar(backoffSlots) * m_slotTime;
+  return (backoff);
+}
+
+void Backoff::ResetBackoffTime (void)
+{
+  m_numBackoffRetries = 0;
+}
+
+bool Backoff::MaxRetriesReached(void) {
+  return (m_numBackoffRetries >= m_maxRetries);
+}
+
+void Backoff::IncrNumRetries(void) {
+  m_numBackoffRetries++;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma/backoff.h	Wed Sep 05 18:35:39 2007 +0100
@@ -0,0 +1,87 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 Emmanuelle Laprise
+ *
+ * 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
+ *