Merge with ns-3-dev
authorRaj Bhattacharjea <raj.b@gatech.edu>
Wed, 04 Jun 2008 17:19:32 -0400
changeset 3248 39f736210ab2
parent 3247 05e66ff64e10 (current diff)
parent 3229 ec45f705b9ca (diff)
child 3249 a7203cfb5f37
Merge with ns-3-dev
doc/tutorial/dumbbell.png
doc/tutorial/oneobj.png
doc/tutorial/pp.png
doc/tutorial/star.png
doc/tutorial/threeobj.png
examples/tcp-large-transfer.cc
src/common/data-writer.cc
src/common/data-writer.h
src/common/tag-registry.cc
src/common/tag-registry.h
src/common/tags.cc
src/common/tags.h
src/internet-node/ascii-trace.cc
src/internet-node/ascii-trace.h
src/internet-node/ipv4-header.cc
src/internet-node/ipv4-header.h
src/internet-node/pcap-trace.cc
src/internet-node/pcap-trace.h
src/internet-node/tcp-socket-impl.cc
src/mobility/mobility-model-notifier.cc
src/mobility/mobility-model-notifier.h
src/node/socket-defaults.cc
src/node/socket-defaults.h
src/node/socket.cc
src/node/socket.h
--- a/.hgtags	Fri May 30 15:31:50 2008 -0400
+++ b/.hgtags	Wed Jun 04 17:19:32 2008 -0400
@@ -12,3 +12,4 @@
 b5bf2588cde2f1273b1095cc5c83a0c272e55370 release ns-3.0.10
 ee5e1da76ecc52337f097cd90ebb50a3d49ec541 release-3.0.11
 b17f2928291eec5bf5b1c59a4a5fd583f704ac40 release ns-3.0.12
+79dba133b5f8a2d6f6f678a22e8519bc155e6a4e release ns-3.0.13
--- a/RELEASE_NOTES	Fri May 30 15:31:50 2008 -0400
+++ b/RELEASE_NOTES	Wed Jun 04 17:19:32 2008 -0400
@@ -3,6 +3,26 @@
 
 This file contains ns-3 release notes (most recent releases first).
 
+Release 3.0.13 (2008/06/02)
+========================
+- point to point links generate ppp pcap traces
+- point to point links support asymmetrical data rates.
+- generate doxygen documentation for all attributes and trace sources
+- add ConfigStore and GtkConfigStore to contrib module
+- socket API now support tx and rx buffers: implemented for UDP and TCP
+- ARP cache now supports per-entry pending queues
+- lots of bugfixes and implementation and API cleanups
+
+Warning: among API changes in this release, Application::Start and 
+Application::Stop now interprets the time argument as a relative
+instead of absolute simulation time, to align with how Simulator::Schedule
+behaves.  Any code that calls these APIs in the middle of the simulation 
+will need to be adapted.  
+
+The API of Simulator::StopAt (time) has also changed.  Now it is 
+called Simulator::Stop (time), and takes a relative time, instead of 
+absolute.
+
 Release 3.0.12 (2008/04/07)
 ========================
     - Add Attribute support to the TypeId metadata system and add
--- a/VERSION	Fri May 30 15:31:50 2008 -0400
+++ b/VERSION	Wed Jun 04 17:19:32 2008 -0400
@@ -1,1 +1,1 @@
-3.0.12
+3.0.13
--- a/doc/modules	Fri May 30 15:31:50 2008 -0400
+++ b/doc/modules	Wed Jun 04 17:19:32 2008 -0400
@@ -13,7 +13,7 @@
  *    - a Functor class: ns3::Callback  
  *    - an os-independent interface to get access to the elapsed wall clock time: ns3::SystemWallClockMs 
  *    - a class to register regression tests with the test manager: ns3::Test and ns3::TestManager
- *    - debugging facilities: \ref logging, \ref assert, \ref error
+ *    - debugging facilities: \ref logging, \ref assert
  *    - \ref randomvariable
  *    - a base class for objects which need to support per-instance "attributes" and
  *      trace sources: ns3::ObjectBase
@@ -24,7 +24,7 @@
  *      in a simulation: ns3::Config.
  *
  * @defgroup common Common
- * The "core" module contains: 
+ * The "common" module contains: 
  *    - a packet class to create and manipulate simulation packets: 
  *      ns3::Packet, ns3::Header,  and ns3::Trailer. This packet class 
  *      also supports per-packet ns3::Tag which are  globs of data 
@@ -62,4 +62,4 @@
  * @brief Constants you can change
  *
  * @defgroup contrib Contrib
- */
\ No newline at end of file
+ */
--- a/doc/release_steps.txt	Fri May 30 15:31:50 2008 -0400
+++ b/doc/release_steps.txt	Wed Jun 04 17:19:32 2008 -0400
@@ -6,7 +6,7 @@
    - revise and check in RELEASE_NOTES
    - update and check in VERSION to the latest release number
    - confirm that Doxygen builds cleanly and without warnings
-     (./waf --doxygen), and check in any necessary changes 
+     (./waf check; ./waf --doxygen), and check in any necessary changes 
 2. ./waf configure; ./waf dist
    - this will create a ns-3.0.x.tar.bz2 tarball
    - this will also create a ns-3.0.x-ref-traces.tar.bz2 tarball
@@ -23,7 +23,7 @@
 6. Run the regression tests on the new release and update the reference traces
    - ./waf --regression
    - ./waf --valgrind --regression (for valgrind version)
-   - There should be no regressions at this time
+   - There should be no regression errors at this time
    - tag ns-3-dev-ref-traces with "release ns-3.0.X"
      hg tag "release ns-3.0.x"
      hg push
--- a/doc/tutorial/Makefile	Fri May 30 15:31:50 2008 -0400
+++ b/doc/tutorial/Makefile	Wed Jun 04 17:19:32 2008 -0400
@@ -2,13 +2,21 @@
 TEXI2PDF = texi2dvi --pdf
 EPSTOPDF = epstopdf
 TGIF = tgif 
+DIA = dia
 CONVERT = convert
 CSS = --css-include=tutorial.css
 SPLIT = --split section
 
-TGIF_SOURCES = helpers.obj 
+DIA_SOURCES = buffer.dia pp.dia dumbbell.dia star.dia sockets-overview.dia
+TGIF_SOURCES = packet.obj helpers.obj 
+
+DIA_EPS = ${DIA_SOURCES:.dia=.eps}
+DIA_PNG = ${DIA_SOURCES:.dia=.png}
+DIA_PDF = ${DIA_SOURCES:.dia=.pdf}
+
 TGIF_EPS = ${TGIF_SOURCES:.obj=.eps}
-TGIF_PNG = ${TGIF_SOURCES:.obj=.eps}
+TGIF_PNG = ${TGIF_SOURCES:.obj=.png}
+TGIF_PDF = ${TGIF_SOURCES:.obj=.pdf}
 
 all:  images html split-html pdf
 
@@ -17,8 +25,11 @@
 #        buffer may be needed (xorg-x11-server-Xvfb) to provide a "fake"
 #        display
 images:
+	cd figures/; $(DIA) -t png $(DIA_SOURCES) 
+	cd figures/; $(DIA) -t eps $(DIA_SOURCES) 
+	cd figures/; $(foreach FILE,$(DIA_EPS),$(EPSTOPDF) $(FILE);)
+	cd figures/; $(TGIF) -print -png $(TGIF_SOURCES) 
 	cd figures/; $(TGIF) -print -eps $(TGIF_SOURCES) 
-	cd figures/; $(TGIF) -print -png $(TGIF_SOURCES) 
 	cd figures/; $(foreach FILE,$(TGIF_EPS),$(EPSTOPDF) $(FILE);)
 
 html: images
@@ -30,5 +41,9 @@
 pdf: images
 	$(TEXI2PDF) tutorial.texi
 
-clean:
+figures-clean:
+	cd figures/; rm -rf $(DIA_EPS); rm -rf $(DIA_PNG); rm -rf $(DIA_PDF)
+	cd figures/; rm -rf $(TGIF_EPS); rm -rf $(TGIF_PNG); rm -rf $(TGIF_PDF)
+
+clean: figures-clean
 	rm -rf tutorial.aux tutorial.cp tutorial.cps tutorial.fn tutorial.ky tutorial.pg tutorial.tp tutorial.vr tutorial.toc tutorial.log tutorial.pdf tutorial.html tutorial/ 
Binary file doc/tutorial/dumbbell.png has changed
--- a/doc/tutorial/figures/README	Fri May 30 15:31:50 2008 -0400
+++ b/doc/tutorial/figures/README	Wed Jun 04 17:19:32 2008 -0400
@@ -1,8 +1,17 @@
 Please write image files in a vector graphics format, when possible, and
 generate the .png and .pdf versions on the fly (see ../Makefile).  
 
-Recommended tools are dia, tgif, and xfig.  Store the .dia, .obj, or .fig 
-versions in mercurial, but not the .png or .pdfs.
+Currently supported tools are dia and tgif.  xfig could be added similarly
+if someone wants to add it.  The main requirement for adding another format
+is that the tool to edit it is freely available and that a cron script can 
+autogenerate the pdf and png from the figure source.
+
+Store the .dia, or .obj versions in mercurial, but not the .png or .pdfs.  
+If the figure is not available in a vector graphics format, store both
+a .png and a .pdf version in this directory.
+
+If you add a source (.dia, .obj) file here, remember to add it to
+the list of figure sources in the Makefile in the directory above
 
 Note:  tgif can convert from .obj to .pdf, but the pdf that results takes
 up a whole page.  Instead, we convert to an intermediate .eps step, and
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/figures/buffer.dia	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,1623 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<dia:diagram xmlns:dia="http://www.lysator.liu.se/~alla/dia/">
+  <dia:diagramdata>
+    <dia:attribute name="background">
+      <dia:color val="#ffffff"/>
+    </dia:attribute>
+    <dia:attribute name="pagebreak">
+      <dia:color val="#000099"/>
+    </dia:attribute>
+    <dia:attribute name="paper">
+      <dia:composite type="paper">
+        <dia:attribute name="name">
+          <dia:string>#A4#</dia:string>
+        </dia:attribute>
+        <dia:attribute name="tmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="bmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="lmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="rmargin">
+          <dia:real val="2.8222000598907471"/>
+        </dia:attribute>
+        <dia:attribute name="is_portrait">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="scaling">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="fitto">
+          <dia:boolean val="false"/>
+        </dia:attribute>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="grid">
+      <dia:composite type="grid">
+        <dia:attribute name="width_x">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="width_y">
+          <dia:real val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_x">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:attribute name="visible_y">
+          <dia:int val="1"/>
+        </dia:attribute>
+        <dia:composite type="color"/>
+      </dia:composite>
+    </dia:attribute>
+    <dia:attribute name="color">
+      <dia:color val="#d8e5e5"/>
+    </dia:attribute>
+    <dia:attribute name="guides">
+      <dia:composite type="guides">
+        <dia:attribute name="hguides"/>
+        <dia:attribute name="vguides"/>
+      </dia:composite>
+    </dia:attribute>
+  </dia:diagramdata>
+  <dia:layer name="Background" visible="true">
+    <dia:object type="Flowchart - Box" version="0" id="O0">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.95,-17.05;8.05,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="5,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="3"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Count#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="6.5,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O1">
+      <dia:attribute name="obj_pos">
+        <dia:point val="8,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="7.95,-17.05;11.05,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="8,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="3"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Size#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="9.5,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O2">
+      <dia:attribute name="obj_pos">
+        <dia:point val="10.825,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="10.775,-17.05;15.225,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="10.825,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="4.3499999999999996"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Initial Start#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="13,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O3">
+      <dia:attribute name="obj_pos">
+        <dia:point val="15,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="14.95,-17.05;19.05,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="15,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="4"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Dirty Start#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="17,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O4">
+      <dia:attribute name="obj_pos">
+        <dia:point val="22.925,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="22.875,-17.05;29.1,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="22.925,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="6.1249999999999964"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#90ee90"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Unused Area#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="25.9875,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O5">
+      <dia:attribute name="obj_pos">
+        <dia:point val="19,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="18.95,-17.05;23.05,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="19,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="4"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Dirty Size#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="21,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O6">
+      <dia:attribute name="obj_pos">
+        <dia:point val="17,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="16.93,-15.3378;29.4316,-14.6622"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="17,-15"/>
+        <dia:point val="20,-11"/>
+        <dia:point val="26.0375,-11"/>
+        <dia:point val="29,-15"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O3" connection="13"/>
+        <dia:connection handle="3" to="O9" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O7">
+      <dia:attribute name="obj_pos">
+        <dia:point val="21,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="20.93,-15.3378;42.4316,-14.6622"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="21,-15"/>
+        <dia:point val="24,-11"/>
+        <dia:point val="39.0375,-11"/>
+        <dia:point val="42,-15"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O5" connection="13"/>
+        <dia:connection handle="3" to="O9" connection="15"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O8">
+      <dia:attribute name="obj_pos">
+        <dia:point val="9.5,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="9.4309,-15.4359;48.4563,-9.59687"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="9.5,-15"/>
+        <dia:point val="23.5,-6"/>
+        <dia:point val="41.125,-10"/>
+        <dia:point val="48.125,-15"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O1" connection="13"/>
+        <dia:connection handle="3" to="O14" connection="15"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O9">
+      <dia:attribute name="obj_pos">
+        <dia:point val="29,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="28.95,-17.05;42.05,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="29,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="13"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#a52a2a"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Dirty Area#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="35.5,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O10">
+      <dia:attribute name="obj_pos">
+        <dia:point val="13,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="12.9296,-15.34;40.43,-11.1632"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="13,-15"/>
+        <dia:point val="18,-9"/>
+        <dia:point val="37,-11"/>
+        <dia:point val="40,-15"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O2" connection="13"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O11">
+      <dia:attribute name="obj_pos">
+        <dia:point val="40,-22"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="30.9298,-29.0702;40.0702,-21.9298"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="40,-22"/>
+        <dia:point val="31,-29"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="1" to="O13" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O12">
+      <dia:attribute name="obj_pos">
+        <dia:point val="40,-22"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="39.9293,-29.0707;47.0707,-21.9293"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="40,-22"/>
+        <dia:point val="47,-29"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="1" to="O13" connection="15"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O13">
+      <dia:attribute name="obj_pos">
+        <dia:point val="31,-31"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="30.95,-31.05;47.05,-28.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="31,-31"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="16"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Virtual Zero Area#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="39,-29.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O14">
+      <dia:attribute name="obj_pos">
+        <dia:point val="42,-17"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="41.95,-17.05;48.175,-14.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="42,-17"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="6.1249999999999964"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#90ee90"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Unused Area#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="45.0625,-15.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:group>
+      <dia:object type="Flowchart - Box" version="0" id="O15">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5,-31"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.95,-31.05;9.05,-28.95"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="5,-31"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="4"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Data#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7,-29.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O16">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9,-31"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.95,-31.05;15.15,-28.95"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9,-31"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="6.1000000000000014"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Zero Area Size#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="12.05,-29.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O17">
+        <dia:attribute name="obj_pos">
+          <dia:point val="15,-31"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="14.95,-31.05;21.05,-28.95"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="15,-31"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="6"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Used start#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="18,-29.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O18">
+        <dia:attribute name="obj_pos">
+          <dia:point val="21,-31"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="20.95,-31.05;26.05,-28.95"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="21,-31"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="5"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Used Size#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="23.5,-29.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+    </dia:group>
+    <dia:group>
+      <dia:object type="Flowchart - Box" version="0" id="O19">
+        <dia:attribute name="obj_pos">
+          <dia:point val="5,-2"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="4.95,-2.05;9.05,0.05"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="5,-2"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="4"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Data#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="7,-0.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O20">
+        <dia:attribute name="obj_pos">
+          <dia:point val="9,-2"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="8.95,-2.05;15.15,0.05"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="9,-2"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="6.1000000000000014"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Zero Area Size#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="12.05,-0.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O21">
+        <dia:attribute name="obj_pos">
+          <dia:point val="15,-2"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="14.95,-2.05;21.05,0.05"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="15,-2"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="6"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Used start#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="18,-0.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+      <dia:object type="Flowchart - Box" version="0" id="O22">
+        <dia:attribute name="obj_pos">
+          <dia:point val="21,-2"/>
+        </dia:attribute>
+        <dia:attribute name="obj_bb">
+          <dia:rectangle val="20.95,-2.05;26.05,0.05"/>
+        </dia:attribute>
+        <dia:attribute name="elem_corner">
+          <dia:point val="21,-2"/>
+        </dia:attribute>
+        <dia:attribute name="elem_width">
+          <dia:real val="5"/>
+        </dia:attribute>
+        <dia:attribute name="elem_height">
+          <dia:real val="2"/>
+        </dia:attribute>
+        <dia:attribute name="show_background">
+          <dia:boolean val="true"/>
+        </dia:attribute>
+        <dia:attribute name="padding">
+          <dia:real val="0.10000000000000001"/>
+        </dia:attribute>
+        <dia:attribute name="text">
+          <dia:composite type="text">
+            <dia:attribute name="string">
+              <dia:string>#Used Size#</dia:string>
+            </dia:attribute>
+            <dia:attribute name="font">
+              <dia:font family="sans" style="0" name="Helvetica"/>
+            </dia:attribute>
+            <dia:attribute name="height">
+              <dia:real val="1.1000000000000001"/>
+            </dia:attribute>
+            <dia:attribute name="pos">
+              <dia:point val="23.5,-0.75"/>
+            </dia:attribute>
+            <dia:attribute name="color">
+              <dia:color val="#000000"/>
+            </dia:attribute>
+            <dia:attribute name="alignment">
+              <dia:enum val="1"/>
+            </dia:attribute>
+          </dia:composite>
+        </dia:attribute>
+      </dia:object>
+    </dia:group>
+    <dia:object type="Standard - Line" version="0" id="O23">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7,-2"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.49821,-15.1254;7.05702,-1.94298"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7,-2"/>
+        <dia:point val="5,-15"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O19" connection="2"/>
+        <dia:connection handle="1" to="O0" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O24">
+      <dia:attribute name="obj_pos">
+        <dia:point val="7,-29"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="4.49858,-29.0575;7.05754,-16.8685"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="7,-29"/>
+        <dia:point val="5,-17"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O15" connection="13"/>
+        <dia:connection handle="1" to="O0" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O25">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12.05,-31"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="11.9915,-34.0955;39.3889,-30.6111"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="12.05,-31"/>
+        <dia:point val="13,-36"/>
+        <dia:point val="36,-34"/>
+        <dia:point val="39,-31"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O16" connection="2"/>
+        <dia:connection handle="3" to="O13" connection="2"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O26">
+      <dia:attribute name="obj_pos">
+        <dia:point val="18,-29"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.9318,-29.0682;33.2055,-21.5098"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="18,-29"/>
+        <dia:point val="22,-22"/>
+        <dia:point val="30,-23"/>
+        <dia:point val="33,-22"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O17" connection="13"/>
+        <dia:connection handle="3" to="O28" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O27">
+      <dia:attribute name="obj_pos">
+        <dia:point val="24,-29"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="23.9293,-29.0707;41.5,-21.95"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="24,-29"/>
+        <dia:point val="28,-25"/>
+        <dia:point val="41,-27"/>
+        <dia:point val="41,-22"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="3" to="O28" connection="4"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O28">
+      <dia:attribute name="obj_pos">
+        <dia:point val="33,-22"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="32.95,-22.05;41.05,-19.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="33,-22"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="8"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#1e90ff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Used#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="37,-20.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O29">
+      <dia:attribute name="obj_pos">
+        <dia:point val="35,-8"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="34.95,-8.05;42.05,-5.95"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="35,-8"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="7"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="inner_color">
+        <dia:color val="#1e90ff"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Used#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="38.5,-6.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O30">
+      <dia:attribute name="obj_pos">
+        <dia:point val="12.05,0"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="11.9807,-0.294111;39.3576,4.18349"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="12.05,0"/>
+        <dia:point val="16,6"/>
+        <dia:point val="36,5"/>
+        <dia:point val="38.9,0"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O20" connection="13"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O31">
+      <dia:attribute name="obj_pos">
+        <dia:point val="40,-6"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="32.9318,-6.06822;40.0682,-1.93178"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="40,-6"/>
+        <dia:point val="33,-2"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="1" to="O33" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O32">
+      <dia:attribute name="obj_pos">
+        <dia:point val="40,-6"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="39.9329,-6.06708;42.0671,-1.93292"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="40,-6"/>
+        <dia:point val="42,-2"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="1" to="O33" connection="4"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Flowchart - Box" version="0" id="O33">
+      <dia:attribute name="obj_pos">
+        <dia:point val="33,-2"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="32.95,-2.05;42.05,0.05"/>
+      </dia:attribute>
+      <dia:attribute name="elem_corner">
+        <dia:point val="33,-2"/>
+      </dia:attribute>
+      <dia:attribute name="elem_width">
+        <dia:real val="9"/>
+      </dia:attribute>
+      <dia:attribute name="elem_height">
+        <dia:real val="2"/>
+      </dia:attribute>
+      <dia:attribute name="show_background">
+        <dia:boolean val="true"/>
+      </dia:attribute>
+      <dia:attribute name="padding">
+        <dia:real val="0.10000000000000001"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Virtual Zero Area#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="37.5,-0.75"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="1"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O34">
+      <dia:attribute name="obj_pos">
+        <dia:point val="18,-2"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="17.9343,-7.50205;35.1202,-1.93435"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="18,-2"/>
+        <dia:point val="25,-5"/>
+        <dia:point val="28,-6"/>
+        <dia:point val="35,-7"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O21" connection="2"/>
+        <dia:connection handle="3" to="O29" connection="7"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - BezierLine" version="0" id="O35">
+      <dia:attribute name="obj_pos">
+        <dia:point val="23.5,-2"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="23.4296,-8.86763;42.2683,-1.92958"/>
+      </dia:attribute>
+      <dia:attribute name="bez_points">
+        <dia:point val="23.5,-2"/>
+        <dia:point val="26,-5"/>
+        <dia:point val="36,-11"/>
+        <dia:point val="42,-8"/>
+      </dia:attribute>
+      <dia:attribute name="corner_types">
+        <dia:enum val="0"/>
+        <dia:enum val="0"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow">
+        <dia:enum val="22"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_length">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:attribute name="end_arrow_width">
+        <dia:real val="0.5"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O22" connection="2"/>
+        <dia:connection handle="3" to="O29" connection="4"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O36">
+      <dia:attribute name="obj_pos">
+        <dia:point val="33,-20"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="32.95,-20.05;33.05,-16.95"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="33,-20"/>
+        <dia:point val="33,-17"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O28" connection="11"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O37">
+      <dia:attribute name="obj_pos">
+        <dia:point val="41,-20"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="40.95,-20.05;41.05,-16.95"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="41,-20"/>
+        <dia:point val="41,-17"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O28" connection="15"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O38">
+      <dia:attribute name="obj_pos">
+        <dia:point val="35,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="34.95,-15.05;35.05,-7.95"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="35,-15"/>
+        <dia:point val="35,-8"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="1" to="O29" connection="0"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O39">
+      <dia:attribute name="obj_pos">
+        <dia:point val="40,-22"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="39.95,-22.05;40.05,-5.95"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="40,-22"/>
+        <dia:point val="40,-6"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Line" version="0" id="O40">
+      <dia:attribute name="obj_pos">
+        <dia:point val="42,-15"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="41.95,-15.05;42.05,-7.95"/>
+      </dia:attribute>
+      <dia:attribute name="conn_endpoints">
+        <dia:point val="42,-15"/>
+        <dia:point val="42,-8"/>
+      </dia:attribute>
+      <dia:attribute name="numcp">
+        <dia:int val="1"/>
+      </dia:attribute>
+      <dia:attribute name="line_style">
+        <dia:enum val="4"/>
+      </dia:attribute>
+      <dia:connections>
+        <dia:connection handle="0" to="O9" connection="15"/>
+        <dia:connection handle="1" to="O29" connection="4"/>
+      </dia:connections>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O41">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5,1"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5,0.175;7.125,1.55"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Buffer#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="5,1"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O42">
+      <dia:attribute name="obj_pos">
+        <dia:point val="6,-14"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="6,-14.825;9.825,-13.45"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#BufferData#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="6,-14"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+    <dia:object type="Standard - Text" version="1" id="O43">
+      <dia:attribute name="obj_pos">
+        <dia:point val="5,-32"/>
+      </dia:attribute>
+      <dia:attribute name="obj_bb">
+        <dia:rectangle val="5,-32.825;7.125,-31.45"/>
+      </dia:attribute>
+      <dia:attribute name="text">
+        <dia:composite type="text">
+          <dia:attribute name="string">
+            <dia:string>#Buffer#</dia:string>
+          </dia:attribute>
+          <dia:attribute name="font">
+            <dia:font family="sans" style="0" name="Helvetica"/>
+          </dia:attribute>
+          <dia:attribute name="height">
+            <dia:real val="1.1000000000000001"/>
+          </dia:attribute>
+          <dia:attribute name="pos">
+            <dia:point val="5,-32"/>
+          </dia:attribute>
+          <dia:attribute name="color">
+            <dia:color val="#000000"/>
+          </dia:attribute>
+          <dia:attribute name="alignment">
+            <dia:enum val="0"/>
+          </dia:attribute>
+        </dia:composite>
+      </dia:attribute>
+      <dia:attribute name="valign">
+        <dia:enum val="3"/>
+      </dia:attribute>
+    </dia:object>
+  </dia:layer>
+</dia:diagram>
Binary file doc/tutorial/figures/dumbbell.dia has changed
Binary file doc/tutorial/figures/oneobj.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/figures/packet.obj	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,227 @@
+%TGIF 4.1.43-QPL
+state(0,37,100.000,0,64,0,32,0,9,1,1,1,0,0,0,1,0,'Courier-Bold',1,103680,0,3,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,2880,0).
+%
+% @(#)$Header$
+% %W%
+%
+unit("1 pixel/pixel").
+color_info(11,65535,0,[
+	"magenta", 65535, 0, 65535, 65535, 0, 65535, 1,
+	"red", 65535, 0, 0, 65535, 0, 0, 1,
+	"green", 0, 65535, 0, 0, 65535, 0, 1,
+	"blue", 0, 0, 65535, 0, 0, 65535, 1,
+	"yellow", 65535, 65535, 0, 65535, 65535, 0, 1,
+	"pink", 65535, 49344, 52171, 65535, 49344, 52171, 1,
+	"cyan", 0, 65535, 65535, 0, 65535, 65535, 1,
+	"CadetBlue", 24415, 40606, 41120, 24415, 40606, 41120, 1,
+	"white", 65535, 65535, 65535, 65535, 65535, 65535, 1,
+	"black", 0, 0, 0, 0, 0, 0, 1,
+	"DarkSlateGray", 12079, 20303, 20303, 12079, 20303, 20303, 1
+]).
+script_frac("0.6").
+fg_bg_colors('black','white').
+dont_reencode("FFDingbests:ZapfDingbats").
+page(1,"",1,'').
+box('black','',32,48,240,256,0,3,1,0,0,0,0,0,0,'3',0,[
+]).
+text('black',64,10,1,0,1,121,28,3,22,6,0,0,0,0,2,121,28,0,0,"",0,0,0,0,32,'',[
+minilines(121,28,0,0,0,0,0,[
+mini_line(121,22,6,0,0,0,[
+str_block(0,121,22,6,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,138240,121,22,6,0,0,0,0,0,0,0,
+	"class Packet")])
+])
+])]).
+text('black',416,100,1,0,1,116,28,15,22,6,0,0,0,0,2,116,28,0,0,"",0,0,0,0,122,'',[
+minilines(116,28,0,0,0,0,0,[
+mini_line(116,22,6,0,0,0,[
+str_block(0,116,22,6,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,138240,116,22,6,0,0,0,0,0,0,0,
+	"class Buffer")])
+])
+])]).
+text('black',48,178,4,0,1,83,69,32,14,4,0,0,0,0,2,83,69,0,0,"",0,0,0,0,192,'',[
+minilines(83,69,0,0,0,0,0,[
+mini_line(80,14,4,0,0,0,[
+str_block(0,80,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
+	"private data:")])
+]),
+mini_line(59,14,3,0,0,0,[
+str_block(0,59,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,59,14,3,0,0,0,0,0,0,0,
+	"- unique id")])
+]),
+mini_line(83,14,3,0,0,0,[
+str_block(0,83,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,83,14,3,0,0,0,0,0,0,0,
+	"- Buffer object")])
+]),
+mini_line(76,14,3,0,0,0,[
+str_block(0,76,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,76,14,3,0,0,0,0,0,0,0,
+	"- Tags object")])
+])
+])]).
+text('black',112,288,1,0,1,103,28,82,22,6,0,0,0,0,2,103,28,0,0,"",0,0,0,0,310,'',[
+minilines(103,28,0,0,0,0,0,[
+mini_line(103,22,6,0,0,0,[
+str_block(0,103,22,6,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,138240,103,22,6,0,-1,0,0,0,0,0,
+	"class Tags")])
+])
+])]).
+text('black',48,50,5,0,1,175,86,176,14,4,0,0,0,0,2,175,86,0,0,"",0,0,0,0,64,'',[
+minilines(175,86,0,0,0,0,0,[
+mini_line(105,14,4,0,0,0,[
+str_block(0,105,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
+	"public functions:")])
+]),
+mini_line(80,14,3,0,0,0,[
+str_block(0,80,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,80,14,3,0,-1,0,0,0,0,0,
+	"- constructors")])
+]),
+mini_line(175,14,3,0,0,0,[
+str_block(0,175,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,175,14,3,0,-1,0,0,0,0,0,
+	"- add/remove/peek at Headers")])
+]),
+mini_line(155,14,3,0,0,0,[
+str_block(0,155,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,155,14,3,0,-1,0,0,0,0,0,
+	"- add/remove/peek at Tags")])
+]),
+mini_line(88,14,3,0,0,0,[
+str_block(0,88,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,88,14,3,0,0,0,0,0,0,0,
+	"- fragmentation")])
+])
+])]).
+box('black','',384,144,614,352,0,3,1,245,0,0,0,0,0,'3',0,[
+]).
+text('black',400,274,4,0,1,204,69,246,14,4,0,0,0,0,2,204,69,0,0,"",0,0,0,0,288,'',[
+minilines(204,69,0,0,0,0,0,[
+mini_line(80,14,4,0,0,0,[
+str_block(0,80,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
+	"private data:")])
+]),
+mini_line(193,14,3,0,0,0,[
+str_block(0,193,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,193,14,3,0,0,0,0,0,0,0,
+	"- struct BufferData, a dynamically")])
+]),
+mini_line(160,14,3,0,0,0,[
+str_block(0,160,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,160,14,3,0,0,0,0,0,0,0,
+	"varying byte buffer to which")])
+]),
+mini_line(204,14,3,0,0,0,[
+str_block(0,204,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,204,14,3,0,0,0,0,0,0,0,
+	"data can be prepended or appended")])
+])
+])]).
+text('black',400,146,5,0,1,188,86,247,14,4,0,0,0,0,2,188,86,0,0,"",0,0,0,0,160,'',[
+minilines(188,86,0,0,0,0,0,[
+mini_line(105,14,4,0,0,0,[
+str_block(0,105,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
+	"public functions:")])
+]),
+mini_line(172,14,3,0,0,0,[
+str_block(0,172,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,172,14,3,0,0,0,0,0,0,0,
+	"- Iterators to move byte buffer")])
+]),
+mini_line(171,14,3,0,0,0,[
+str_block(0,171,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,171,14,3,0,0,0,0,0,0,0,
+	"pointers forward or backward")])
+]),
+mini_line(188,14,3,0,0,0,[
+str_block(0,188,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,188,14,3,0,0,0,0,0,0,0,
+	"- functions to read and write data")])
+]),
+mini_line(132,14,3,0,0,0,[
+str_block(0,132,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,132,14,3,0,-1,0,0,0,0,0,
+	"of various sized chunks")])
+])
+])]).
+box('black','',96,324,304,532,0,3,1,264,0,0,0,0,0,'3',0,[
+]).
+text('black',112,454,4,0,1,167,69,265,14,4,0,0,0,0,2,167,69,0,0,"",0,0,0,0,468,'',[
+minilines(167,69,0,0,0,0,0,[
+mini_line(80,14,4,0,0,0,[
+str_block(0,80,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,80,14,4,0,-1,0,0,0,0,0,
+	"private data:")])
+]),
+mini_line(167,14,3,0,0,0,[
+str_block(0,167,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,167,14,3,0,0,0,0,0,0,0,
+	"- singly linked-list of TagData")])
+]),
+mini_line(158,14,3,0,0,0,[
+str_block(0,158,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,158,14,3,0,0,0,0,0,0,0,
+	"structures, with a reference")])
+]),
+mini_line(32,14,3,0,0,0,[
+str_block(0,32,14,3,0,0,0,0,0,[
+str_seg('black','Times-Roman',0,80640,32,14,3,0,0,0,0,0,0,0,
+	"count")])
+])
+])]).
+text('black',112,326,5,0,1,155,86,266,14,4,0,0,0,0,2,155,86,0,0,"",0,0,0,0,340,'',[
+minilines(155,86,0,0,0,0,0,[
+mini_line(105,14,4,0,0,0,[
+str_block(0,105,14,4,0,-1,0,0,0,[
+str_seg('black','Times-Bold',1,80640,105,14,4,0,-1,0,0,0,0,0,
+	"public functions:")])
+]),
+mini_line(80,14,3,0,0,0,[
+str_block(0,80,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,80,14,3,0,-1,0,0,0,0,0,
+	"- constructors")])
+]),
+mini_line(155,14,3,0,0,0,[
+str_block(0,155,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,155,14,3,0,-1,0,0,0,0,0,
+	"- templates to add, remove,")])
+]),
+mini_line(148,14,3,0,0,0,[
+str_block(0,148,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,148,14,3,0,-1,0,0,0,0,0,
+	"or peek at Tags of various")])
+]),
+mini_line(31,14,3,0,0,0,[
+str_block(0,31,14,3,0,-1,0,0,0,[
+str_seg('black','Times-Roman',0,80640,31,14,3,0,-1,0,0,0,0,0,
+	"types")])
+])
+])]).
+poly('black','',2,[
+	59,245,96,320],0,2,1,272,0,0,3,0,0,0,0,'2',0,0,
+    "0","",[
+    0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
+]).
+poly('black','',2,[
+	123,246,288,320],0,2,1,280,0,0,3,0,0,0,0,'2',0,0,
+    "0","",[
+    0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
+]).
+poly('black','',2,[
+	141,219,379,147],0,2,1,286,0,0,3,0,0,0,0,'2',0,0,
+    "0","",[
+    0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
+]).
+poly('black','',2,[
+	132,226,375,335],0,2,1,287,0,0,3,0,0,0,0,'2',0,0,
+    "0","",[
+    0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
+]).
Binary file doc/tutorial/figures/pp.dia has changed
Binary file doc/tutorial/figures/sockets-overview.dia has changed
Binary file doc/tutorial/figures/star.dia has changed
Binary file doc/tutorial/figures/threeobj.png has changed
Binary file doc/tutorial/oneobj.png has changed
--- a/doc/tutorial/other.texi	Fri May 30 15:31:50 2008 -0400
+++ b/doc/tutorial/other.texi	Wed Jun 04 17:19:32 2008 -0400
@@ -34,7 +34,7 @@
 you old-timers) cable.  This topology is shown below.
 
 @sp 1
-@center @image{pp,,,,png}
+@center @image{figures/pp,,,,png}
 
 @cindex CreateObject
 @cindex InternetNode
@@ -173,7 +173,7 @@
 that implements a simple star network as seen below.
 
 @sp 1
-@center @image{star,,,,png}
+@center @image{figures/star,,,,png}
 
 In order to create a star network, we need to be able to instantiate some
 number (greater than one) of net devices on a node.  In the name of simplicity
@@ -506,7 +506,7 @@
 The following is a representation of the topology.
 
 @sp 1
-@center @image{dumbbell,,,,png}
+@center @image{figures/dumbbell,,,,png}
 
 We have provided a file that constructs this dumbbell network and creates 
 enough data flowing across the choke point that some packets will be dropped.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/packets.texi	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,620 @@
+@node ns-3 Packets
+@chapter ns-3 Packets
+
+The design of the Packet framework of @emph{ns} was heavily guided by a few
+important use-cases:
+@itemize @bullet
+@item avoid changing the core of the simulator to introduce
+new types of packet headers or trailers
+@item maximize the ease of integration with real-world code
+and systems
+@item make it easy to support fragmentation, defragmentation,
+and, concatenation which are important, especially in wireless systems.
+@item make memory management of this object efficient
+@item allow actual application data or dummy application bytes for
+emulated applications
+@end itemize
+
+@emph{ns} Packet objects contain a buffer of bytes: protocol headers and
+trailers are serialized in this buffer of bytes using user-provided
+serialization and deserialization routines. The content of this byte
+buffer is expected to match bit-for-bit the content of a real packet on
+a real network implementing the protocol of interest.
+
+Fragmentation and defragmentation are quite natural to implement within
+this context: since we have a buffer of real bytes, we can split it in
+multiple fragments and re-assemble these fragments. We expect that this
+choice will make it really easy to wrap our Packet data structure within
+Linux-style skb or BSD-style mbuf to integrate real-world kernel code in
+the simulator. We also expect that performing a real-time plug of the
+simulator to a real-world network will be easy.
+
+Because we understand that simulation developers often wish to store in
+packet objects data which is not found in the real packets (such as
+timestamps or any kind of similar in-band data), the @emph{ns} Packet class
+can also store extra per-packet "Tags" which are 16 bytes blobs of data.
+Any Packet can store any number of unique Tags, each of which is
+uniquely identified by its C++ type. These tags make it easy to attach
+per-model data to a packet without having to patch the main Packet
+class or Packet facilities.
+
+Memory management of Packet objects is entirely automatic and extremely
+efficient: memory for the application-level payload can be modelized by
+a virtual buffer of zero-filled bytes for which memory is never allocated
+unless explicitely requested by the user or unless the packet is fragmented.
+Furthermore, copying, adding, and, removing headers or trailers to a packet
+has been optimized to be virtually free through a technique known as
+Copy On Write.
+
+Packets (messages) are fundamental objects in the simulator and
+their design is important from a performance and resource management
+perspective.  There
+are various ways to design the simulation packet, and tradeoffs
+among the different approaches.  In particular, there is a 
+tension between ease-of-use, performance, and safe interface
+design. 
+
+There are a few requirements on this object design:
+@itemize @bullet 
+@item Creation, management, and deletion of this object
+should be as simple as possible, while avoiding the
+chance for memory leaks and/or heap corruption; 
+@item Packets should support serialization and deserialization
+so that network emulation is supported;
+@item Packets should support fragmentation and concatenation
+(multiple packets in a data link frame), especially for wireless
+support;
+@item It should be natural for packets to carry actual application
+data, or if there is only an emulated application and there is
+no need to carry dummy bytes, smaller packets could be used with
+just the headers and a record of the payload size, but not actual
+application bytes, conveyed in the simulated packet.
+@item Packets should facilitate BSD-like operations on mbufs, for
+support of ported operating system stacks.
+@item Additional side-information should be supported, such as
+a tag for cross-layer information.
+@end itemize
+
+@section Packet design overview
+
+Unlike @emph{ns-2}, in which Packet objects contain a buffer of C++
+structures corresponding to protocol headers, each network packet in
+@emph{ns-3} contains a byte Buffer and a list of Tags:
+@itemize @bullet
+@item The byte buffer stores the serialized content of the chunks 
+added to a packet. The serialized representation of these chunks 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.
+Packets can also be created with an arbitrary zero-filled payload
+for which no real memory is allocated.
+@item The list of tags stores an arbitrarily large set of arbitrary 
+user-provided data structures in the packet.  Each Tag is uniquely
+identified by its type; only one instance of each 
+type of data structure is allowed in a list of tags. These tags typically 
+contain per-packet cross-layer information or flow identifiers (i.e.,
+things that you wouldn't find in the bits on the wire). Each tag 
+stored in the tag list can be at most 16 bytes.
+Trying to attach bigger data structures will trigger 
+crashes at runtime.  The 16 byte limit is a modifiable compilation
+constant.
+@end itemize
+
+@float Figure,fig:packets
+@caption{Implementation overview of Packet class.}
+@image{figures/packet}
+@end float
+
+Figure @ref{fig:packets} is a high-level overview of the Packet
+implementation; more detail on the byte Buffer implementation
+is provided later in Figure @ref{fig:buffer}.
+In \nsthree, the Packet byte buffer is analogous to a Linux skbuff
+or BSD mbuf; it is a serialized representation of the actual
+data in the packet.  The tag list is a container for extra
+items useful for simulation convenience; if a Packet is converted
+to an emulated packet and put over an actual network, the tags
+are stripped off and the byte buffer is copied directly
+into a real packet.
+
+The Packet class has value semantics:  it can be freely copied around,
+allocated on the stack, and passed to functions as arguments.  Whenever
+an instance is copied, the full underlying data is not copied; it
+has ``copy-on-write'' (COW) semantics.  Packet instances can be passed
+by value to function arguments without any performance hit.
+
+The fundamental classes for adding to and removing from the byte
+buffer are @code{class Header} and @code{class Trailer}.  
+Headers are more common but the below discussion also largely applies to
+protocols using trailers.  Every protocol header that needs to 
+be inserted and removed from a Packet instance should derive from 
+the abstract Header base class and implement the private pure 
+virtual methods listed below:
+@itemize @bullet
+@item @code{ns3::Header::SerializeTo()}
+@item @code{ns3::Header::DeserializeFrom()}
+@item @code{ns3::Header::GetSerializedSize()}
+@item @code{ns3::Header::PrintTo()} 
+@end itemize
+Basically, the first three functions are used to serialize and deserialize
+protocol control information to/from a Buffer.  For example,
+one may define @code{class TCPHeader : public Header}.  The
+TCPHeader object will typically consist of some private data
+(like a sequence number) and public interface access functions
+(such as checking the bounds of an input).  But the underlying
+representation of the TCPHeader in a Packet Buffer is 20 serialized
+bytes (plus TCP options).  The TCPHeader::SerializeTo() function would
+therefore be designed to write these 20 bytes properly into
+the packet, in network byte order.  The last function is used
+to define how the Header object prints itself onto an output stream.  
+
+Similarly, user-defined Tags can be appended to the packet. 
+Unlike Headers, Tags are not serialized into a contiguous buffer
+but are stored in an array.  By default, Tags are limited to 16 bytes in
+size.  Tags can be flexibly defined to be any type, but there
+can only be one instance of any particular object type in
+the Tags buffer at any time.  The implementation makes use
+of templates to generate the proper set of Add(), Remove(),
+and Peek() functions for each Tag type.   
+
+@section Packet interface
+
+The public member functions of a Packet object are as follows:
+
+@subsection Constructors
+@verbatim
+    /**
+     * Create an empty packet with a new uid (as returned
+     * by getUid).
+     */
+    Packet ();
+    /**
+     * Create a packet with a zero-filled payload.
+     * The memory necessary for the payload is not allocated:
+     * it will be allocated at any later point if you attempt
+     * to fragment this packet or to access the zero-filled
+     * bytes. The packet is allocated with a new uid (as
+     * returned by getUid).
+     *
+     * \param size the size of the zero-filled payload
+     */
+    Packet (uint32_t size);
+@end verbatim
+
+@subsection Adding and removing Buffer data
+The below code is reproduced for Header class only; similar functions
+exist for Trailers.
+@verbatim
+    /**
+     * Add header to this packet. This method invokes the
+     * ns3::Header::serializeTo method to request the header to serialize
+     * itself in the packet buffer.
+     *
+     * \param header a reference to the header to add to this packet.
+     */
+    void Add (Header const &header);
+    /**
+     * Deserialize header from this packet. This method invokes the
+     * ns3::Header::deserializeFrom method to request the header to deserialize
+     * itself from the packet buffer. This method does not remove
+     * the data from the buffer. It merely reads it.
+     *
+     * \param header a reference to the header to deserialize from the buffer
+     */
+    void Peek (Header &header);
+    /**
+     * Remove a deserialized header from the internal buffer.
+     * This method removes the bytes read by Packet::peek from
+     * the packet buffer.
+     *
+     * \param header a reference to the header to remove from the internal buffer.
+     */
+    void Remove (Header const &header);
+    /**
+     * Add trailer to this packet. This method invokes the
+     * ns3::Trailer::serializeTo method to request the trailer to serialize
+     * itself in the packet buffer.
+     *
+     * \param trailer a reference to the trailer to add to this packet.
+     */
+@end verbatim
+
+@subsection Adding and removing Tags
+@verbatim
+    /**
+     * 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.
+     *
+     * \param tag a pointer to the tag to attach to this packet.
+     */
+    template <typename T>
+    void AddTag (T const &tag);
+    /**
+     * Remove a tag from this packet. The data stored internally
+     * for this tag is copied in the input tag if an instance
+     * of this tag type is present in the internal buffer. If this
+     * tag type is not present, the input tag is not modified.
+     *
+     * This operation can be potentially slow and might trigger
+     * unexpectedly large memory allocations. It is thus
+     * usually a better idea to create a copy of this packet,
+     * and invoke removeAllTags on the copy to remove all
+     * tags rather than remove the tags one by one from a packet.
+     *
+     * \param tag a pointer to the tag to remove from this packet
+     * \returns true if an instance of this tag type is stored
+     *          in this packet, false otherwise.
+     */
+    template <typename T>
+    bool RemoveTag (T &tag);
+    /**
+     * Copy a tag stored internally to the input tag. If no instance
+     * of this tag is present internally, the input tag is not modified.
+     *
+     * \param tag a pointer to the tag to read from this packet
+     * \returns true if an instance of this tag type is stored
+     *          in this packet, false otherwise.
+     */
+    template <typename T>
+    bool PeekTag (T &tag) const;
+    /**
+     * Remove all the tags stored in this packet. This operation is
+     * much much faster than invoking removeTag n times.
+     */
+    void RemoveAllTags (void);
+@end verbatim
+
+@subsection Fragmentation
+@verbatim
+    /**
+     * Create a new packet which contains a fragment of the original
+     * packet. The returned packet shares the same uid as this packet.
+     *
+     * \param start offset from start of packet to start of fragment to create
+     * \param length length of fragment to create
+     * \returns a fragment of the original packet
+     */
+    Packet CreateFragment (uint32_t start, uint32_t length) const;
+
+        /**
+         * Concatenate the input packet at the end of the current
+         * packet. This does not alter the uid of either packet.
+         * 
+         * \param packet packet to concatenate
+         */
+    void addAtEnd (Packet packet);
+
+        /oncatenate the input packet at the end of the current
+     * packet. This does not alter the uid of either packet.
+     *
+     * \param packet packet to concatenate
+     */
+    void AddAtEnd (Packet packet);
+    /**
+     * Concatenate the fragment of the input packet identified
+     * by the offset and size parameters at the end of the current
+     * packet. This does not alter the uid of either packet.
+     *
+     * \param packet to concatenate
+     * \param offset offset of fragment to copy from the start of the input packet
+     * \param size size of fragment of input packet to copy.
+     */
+    void AddAtEnd (Packet packet, uint32_t offset, uint32_t size);
+    /**
+     * Remove size bytes from the end of the current packet
+     * It is safe to remove more bytes that what is present in
+     * the packet.
+     *
+     * \param size number of bytes from remove
+     */
+    void RemoveAtEnd (uint32_t size);
+    /**
+     * Remove size bytes from the start of the current packet.
+     * It is safe to remove more bytes that what is present in
+     * the packet.
+     *
+     * \param size number of bytes from remove
+     */
+    void RemoveAtStart (uint32_t size);
+@end verbatim
+
+@subsection Miscellaneous
+@verbatim
+    /**
+     * \returns the size in bytes of the packet (including the zero-filled
+     *          initial payload)
+     */
+    uint32_t GetSize (void) const;
+    /**
+     * If you try to change the content of the buffer
+     * returned by this method, you will die.
+     *
+     * \returns a pointer to the internal buffer of the packet.
+     */
+    uint8_t const *PeekData (void) const;
+    /**
+     * A packet is allocated a new uid when it is created
+     * empty or with zero-filled payload.
+     *
+     * \returns an integer identifier which uniquely
+     *          identifies this packet.
+     */
+    uint32_t GetUid (void) const;
+@end verbatim
+
+@section Using Headers
+@emph{walk through an example of adding a UDP header}
+
+@section Using Tags
+@emph{walk through an example of adding a flow ID}
+
+@section Using Fragmentation
+@emph{walk through an example of link-layer fragmentation/reassembly}
+
+@section Sample program
+The below sample program (from @code{ns3/samples/main-packet.cc}) illustrates
+some use of the Packet, Header, and Tag classes.
+
+@verbatim
+/* -*-    Mode:C++; c-basic-offset:4; tab-width:4; 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 void PrintTo (std::ostream &os) const;
+    virtual void SerializeTo (Buffer::Iterator start) const;
+    virtual void DeserializeFrom (Buffer::Iterator start);
+    virtual uint32_t GetSerializedSize (void) const;
+
+    uint16_t m_data;
+};
+
+MyHeader::MyHeader ()
+{}
+MyHeader::~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);
+}
+void 
+MyHeader::DeserializeFrom (Buffer::Iterator start)
+{
+    // deserialize from head of buffer
+    m_data = start.ReadNtohU16 ();
+}
+
+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.Peek (my);
+    p.Remove (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.Add (my);
+    struct MyTag myTag;
+    myTag.m_streamId = 5;
+    p.AddTag (myTag);
+    Receive (p);
+    return 0;
+}
+@end verbatim
+
+@section Implementation details
+
+@subsection Private member variables
+
+A Packet object's interface provides access to some private
+data:
+@verbatim
+    Buffer m_buffer;
+    Tags m_tags;
+    uint32_t m_uid; 
+    static uint32_t m_global_uid;
+@end verbatim
+Each Packet has a Buffer and a Tags object, and a 32-bit unique ID (m\_uid).
+A static member variable keeps track of the UIDs allocated.  Note
+that real network packets do not have a UID; the UID is therefore an
+instance of data that normally would be stored as a Tag in the packet.
+However, it was felt that a UID is a special case that is so often
+used in simulations that it would be more convenient to store it
+in a member variable.
+
+@subsection Buffer implementation
+
+Class Buffer represents a buffer of bytes. Its size is
+automatically adjusted to hold any data prepended
+or appended by the user. Its implementation is optimized
+to ensure that the number of buffer resizes is minimized, 
+by creating new Buffers of the maximum size ever used.
+The correct maximum size is learned at runtime during use by
+recording the maximum size of each packet.
+
+Authors of new Header or Trailer classes need to know the public
+API of the Buffer class.  (add summary here)
+
+The byte buffer is implemented as follows: 
+@verbatim
+    struct BufferData {
+        uint32_t m_count;
+        uint32_t m_size;
+        uint32_t m_initialStart;
+        uint32_t m_dirtyStart;
+        uint32_t m_dirtySize;
+        uint8_t m_data[1];
+    }; 
+    struct BufferData *m_data;
+    uint32_t m_zeroAreaSize;
+    uint32_t m_start;
+    uint32_t m_size;
+@end verbatim
+
+@itemize @bullet
+@item @code{BufferData::m_count}: reference count for BufferData structure
+@item @code{BufferData::m_size}: size of data buffer stored in BufferData structure
+@item @code{BufferData::m_initialStart}: offset from start of data buffer where data was first inserted
+@item @code{BufferData::m_dirtyStart}: offset from start of buffer where every Buffer which holds a reference to this BufferData instance have written data so far
+@item @code{BufferData::m_dirtySize}: size of area where data has been written so far
+@item @code{BufferData::m_data}: pointer to data buffer
+@item @code{Buffer::m_zeroAreaSize}: size of zero area which extends before @code{m_initialStart}
+@item @code{Buffer::m_start}: offset from start of buffer to area used by this buffer
+@item @code{Buffer::m_size}: size of area used by this Buffer in its BufferData structure
+@end itemize
+
+@float Figure,fig:buffer
+@caption{Implementation overview of a packet's byte Buffer.}
+@image{figures/buffer,15cm}
+@end float
+
+This data structure is summarized in Figure @ref{fig:buffer}.
+Each Buffer holds a pointer to an instance of a BufferData.  Most 
+Buffers should be able to share the same underlying BufferData and 
+thus simply increase the BufferData's reference count. If they have to 
+change the content of a BufferData inside the Dirty Area, and if the 
+reference count is not one, they first create a copy of the BufferData and 
+then complete their state-changing operation.
+
+@subsection Tags implementation
+Tags are implemented by a single pointer which points to the start of a 
+linked list ofTagData data structures. Each TagData structure points 
+to the next TagData in the list (its next pointer contains zero to 
+indicate the end of the linked list). Each TagData contains an integer 
+unique id which identifies the type of the tag stored in the TagData.
+@verbatim
+struct TagData {
+    struct TagData *m_next;
+    uint32_t m_id;
+    uint32_t m_count;
+    uint8_t m_data[Tags::SIZE];
+};
+class Tags {        
+    struct TagData *m_next;
+};
+@end verbatim
+
+Adding a tag is a matter of inserting a new TagData at the head of 
+the linked list.  Looking at a tag requires you to find the relevant 
+TagData in the linked list and copy its data into the user data 
+structure. Removing a tag and updating the content of a tag
+requires a deep copy of the linked list before performing this operation. 
+On the other hand, copying a Packet and its tags is a matter of 
+copying the TagData head pointer and incrementing its reference count.
+
+Tags are found by the unique mapping betweent the Tag type and
+its underlying id.  This is why at most one instance of any Tag
+can be stored in a packet.  The mapping between Tag type and 
+underlying id is performed by a registration as follows:
+@verbatim
+/* A sample Tag implementation
+ */
+struct MyTag {
+    uint16_t m_streamId;
+};
+@end verbatim
+
+@emph{add description of TagRegistration for printing}
+
+@subsection Memory management
+
+@emph{Describe free list.}
+
+@emph{Describe dataless vs. data-full packets.}
+
+@subsection Copy-on-write semantics
+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).  This design feature
+and aspects of the public interface borrows from the packet design
+of the Georgia Tech Network Simulator.
+This implementation of COW uses a customized reference counting
+smart pointer class.
+
+What COW 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'' and must therefore invoke
+a true copy.
+
+Dirty operations:
+@itemize @bullet
+@item Packet::RemoveTag()
+@item Packet::Add()
+@item both versions of ns3::Packet::AddAtEnd()
+@end itemize
+
+Non-dirty operations:
+@itemize @bullet
+@item Packet::AddTag()
+@item Packet::RemoveAllTags()
+@item Packet::PeekTag()
+@item Packet::Peek()
+@item Packet::Remove()
+@item Packet::CreateFragment()
+@item Packet::RemoveAtStart()
+@item Packet::RemoveAtEnd()
+@end itemize
+
+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.
+
Binary file doc/tutorial/pp.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/tutorial/sockets.texi	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,243 @@
+@node Sockets APIs
+@chapter Sockets APIs
+
+The @uref{http://en.wikipedia.org/wiki/Berkeley_sockets,,sockets API}
+is a long-standing API used by user-space applications to access
+network services in the kernel.  A ``socket'' is an abstraction, like
+a Unix file handle, that allows applications to connect to other
+Internet hosts and exchange reliable byte streams and unreliable
+datagrams, among other services.   
+
+ns-3 provides two types of sockets APIs, and it is important to
+understand the differences between them.  The first is a @emph{native}
+ns-3 API, while the second uses the services of the native API to 
+provide a @uref{http://en.wikipedia.org/wiki/POSIX,,POSIX-like}
+API as part of an overall application process.  Both APIs strive
+to be close to the typical sockets API that application writers
+on Unix systems are accustomed to, but the POSIX variant is much
+closer to a real system's sockets API.
+
+@section ns-3 sockets API
+
+The native sockets API for ns-3 provides an interface to various
+types of transport protocols (TCP, UDP) as well as to packet sockets
+and, in the future, Netlink-like sockets.  However, users are cautioned
+to understand that the semantics are @strong{not} the exact same as 
+one finds in a real system (for an API which is very much aligned
+to real systems, see the next section).
+
+@code{class ns3::Socket} is defined in @code{src/node/socket.cc,h}.
+Readers will note that many public member functions are aligned
+with real sockets function calls, and all other things being equal,
+we have tried to align with a Posix sockets API.  However, note that:
+
+@itemize @bullet
+@item ns-3 applications handle a smart pointer to a Socket object, not
+a file descriptor;
+@item there is no notion of synchronous API or a ``blocking'' API;
+in fact, the model for interaction between application and socket is
+one of asynchronous I/O, which is not typically found in real systems
+(more on this below);
+@item the C-style socket address structures are not used;
+@item the API is not a complete sockets API, such as supporting
+all socket options or all function variants; 
+@item many calls use @code{ns3::Packet} class to transfer data
+between application and socket.  This may seem a little funny to
+people to pass ``Packets'' across a stream socket API, but think
+of these packets as just fancy byte buffers at this level (more
+on this also below).
+@end itemize
+
+@subsection Basic operation and calls
+
+@float Figure,fig:sockets-overview
+@caption{Implementation overview of native sockets API}
+@image{figures/sockets-overview, 10cm}
+@end float
+
+@subsubsection Creating sockets
+
+An application that wants to use sockets must first create one.
+On real systems, this is accomplished by calling socket():
+@verbatim
+     int
+     socket(int domain, int type, int protocol);
+@end verbatim
+which creates a socket in the system and returns an integer descriptor.
+
+In ns-3, we have no equivalent of a system call at the lower layers,
+so we adopt the following model.  There are certain @emph{factory}
+objects that can create sockets.  Each factory is capable of creating
+one type of socket, and if sockets of a particular type are able to
+be created on a given node, then a factory that can create such sockets
+must be aggregated to the Node. 
+@verbatim
+  static Ptr<Socket> CreateSocket (Ptr<Node> node, TypeId tid);
+@end verbatim
+Examples of TypeIds to pass to this method are @code{TcpSocketFactory}, 
+@code{PacketSocketFactory}, and @code{UdpSocketFactory}.
+
+This method returns a smart pointer to a Socket object.  Here is an
+example:  
+@verbatim
+  Ptr<Node> n0;
+  // Do some stuff to build up the Node's internet stack
+  Ptr<Socket> localSocket = Socket::CreateSocket (n0, TcpSocketFactory::GetTypeId ());
+@end verbatim
+
+In some ns-3 code, sockets will not be explicitly created by user's
+main programs, if an ns-3 application does it.  For instance, for
+@code{class ns3::OnOffApplication}, the function @code{StartApplication()}
+performs the socket creation, and the application holds the socket
+pointer.
+
+@subsubsection Using sockets
+
+Below is a typical sequence of socket calls for a TCP client in a
+real implementation:
+@itemize @bullet
+@item @code{sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);}
+@item @code{bind(sock, ...);}
+@item @code{connect(sock, ...);}
+@item @code{send(sock, ...);}
+@item @code{recv(sock, ...);}
+@item @code{close(sock);}
+@end itemize
+
+There are analogs to all of these calls in ns-3, but we will focus on  
+two aspects here.  First, most usage of sockets in real systems 
+requires a way to manage I/O between the application and kernel.  
+These models include @emph{blocking sockets}, @emph{signal-based I/O},
+and @emph{non-blocking sockets} with polling.  In ns-3, we make use
+of the callback mechanisms to support a fourth mode, which is 
+analogous to POSIX @emph{asynchronous I/O}.
+
+In this model, on the sending side, if the @code{send()} call were to
+fail because of insufficient buffers, the application suspends the
+sending of more data until a function registered at the 
+@code{SetSendCallback()} callback is invoked.  An application can
+also ask the socket how much space is available by calling
+@code{GetTxAvailable ()}.  A typical sequence of events for 
+sending data (ignoring connection setup) might be:
+
+@itemize @bullet
+@item @code{SetSendCallback (MakeCallback(&HandleSendCallback));}
+@item @code{Send ();}
+@item @code{Send ();}
+@item ...
+@item @code{// Send fails because buffer is full}
+@item (wait until HandleSendCallback() is called)
+@item (HandleSendCallback() is called by socket, since space now available)
+@item @code{Send (); // Start sending again}
+@end itemize
+
+Similarly, on the receive side, the socket user does not block on
+a call to @code{recv()}.  Instead, the application sets a callback
+with @code{SetRecvCallback ()} in which the socket will notify the
+application when (and how much) there is data to be read, and
+the application then calls @code{Recv()} to read the data until
+no more can be read.
+
+@subsection Packet vs. buffer variants
+
+There are two basic variants of @code{Send()} and @code{Recv()} supported:
+@verbatim
+  virtual int Send (Ptr<Packet> p) = 0;
+  int Send (const uint8_t* buf, uint32_t size);
+
+  Ptr<Packet> Recv (void);
+  int Recv (uint8_t* buf, uint32_t size);
+@end verbatim
+
+The non-Packet variants are left for legacy API reasons.  When calling
+the raw buffer variant of @code{Send()}, the buffer is immediately
+written into a Packet and the @code{Send (Ptr<Packet> p)} is invoked.
+
+Users may find it semantically odd to pass a Packet to a stream socket
+such as TCP.  However, do not let the name bother you; think of 
+@code{ns3::Packet} to be a fancy byte buffer.  There are a few reasons why
+the Packet variants are more likely to be preferred in ns-3:
+
+@itemize @bullet
+@item Users can use the Tags facility of packets to, for example, encode
+a flow ID or other helper data.
+@item Users can exploit the copy-on-write implementation to avoid
+memory copies (on the receive side, the conversion back to a 
+@code{uint8_t* buf} may sometimes incur an additional copy).
+@item Use of Packet is more aligned with the rest of the ns-3 API
+@end itemize
+
+@subsection Sending dummy data
+
+Sometimes, users want the simulator to just pretend that there is an
+actual data payload in the packet (e.g. to calculate transmission delay)
+but do not want to actually produce or consume the data.  This is
+straightforward to support in ns-3; have applications call
+@code{Create<Packet> (size);} instead of @code{Create<Packet> (buffer, size);}.
+Similarly, passing in a zero to the pointer argument in the raw buffer
+variants has the same effect.  Note that, if some subsequent code tries
+to read the Packet data buffer, the fake buffer will be converted to
+a real (zero'ed) buffer on the spot, and the efficiency will be lost there.
+
+@subsection Socket options
+
+@emph{to be completed}
+
+@subsection Socket errno
+
+@emph{to be completed}
+
+@subsection Example programs
+
+@emph{to be completed}
+
+@section POSIX-like sockets API 
+
+@emph{this capability is under development and is scheduled for
+inclusion in August 2008 timeframe; see the repository
+http://code.nsnam.org/mathieu/ns-3-simu for details}
+
+The below is excerpted from Mathieu's post to ns-developers list
+on April 4, 2008.
+
+"To summarize, the goal is that the full posix/socket API is defined in
+src/process/simu.h: each posix type and function is re-defined there
+with a simu_ or SIMU_ prefix to avoid ugly name clashes and collisions
+(feel free to come up with a better prefix).
+
+Each process is created with a call to ProcessManager::Create and is
+attached to that ProcessManager instance. So, if the ProcessManager
+(which is aggregated to a Node in src/helper/process-helper.cc) is
+killed when the simulation ends, the system will automatically reclaim
+all the resources of each process associated to each manager. The same
+happens when an application "exits" from its main function.
+
+The example application defines two posix "processes": the function
+ClientProgram creates a udp socket on the localhost port 2000 and the
+function ServerProgram creates a udp socket on the localhost port 2000.
+The code does not work right now because I did not get the details of
+simu_read right yet but, I do plan to make this work at some point.
+
+I really think that this approach is worthwhile for many reasons, a few
+of which are outlined below:
+@itemize @bullet
+@item makes porting real world application code _much_ easier
+
+@item makes write applications for new users much easier because they can
+read the bsd socket api reference and documentation and write code
+directly.
+
+@item can be used to write applications which work in both simulation and
+in the real world at the same time. To do this, all you have to do is
+write your application to use the simu_ API, and, then, you can chose at
+compile-time which implementation of that API you want to use: you can
+pick one implementation which forwards all calls to the system BSD
+socket API or another one which forwards all calls to the attached
+ProcessManager. Arguably, I did not implement the version which forwards
+to system BSD sockets but, that should be pretty trivial.
+@end itemize
+
+So, anyway, comments about the overall API would be welcome. Students
+interested in the gsoc project for real-world code integration should
+consider looking at this also."
+
Binary file doc/tutorial/star.png has changed
Binary file doc/tutorial/threeobj.png has changed
--- a/doc/tutorial/tutorial.texi	Fri May 30 15:31:50 2008 -0400
+++ b/doc/tutorial/tutorial.texi	Wed Jun 04 17:19:32 2008 -0400
@@ -93,9 +93,12 @@
 Part 4:  Creating New or Revised Topologies
 * Helper Functions::
 * Other-network-topologies::
-Part 5:  Extending ns-3
+Part 5:  Key ns-3 objects and systems
+* ns-3 Packets::
 * ns-3 Callbacks::
+* Sockets APIs::
 * ns-3 routing overview::
+Part 6:  Extending ns-3
 * Nonlinear-Thinking::
 * Summary::
 * Object-Model::
@@ -111,8 +114,10 @@
 @include attributes.texi
 @include statistics.texi
 @include helpers.texi
+@include packets.texi
 @include callbacks.texi
-@include output.texi
+@include sockets.texi
+@c @include output.texi
 @include routing.texi
 @c @include other.texi
 @include troubleshoot.texi
--- a/examples/csma-packet-socket.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/csma-packet-socket.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -38,9 +38,6 @@
 #include "ns3/node-module.h"
 #include "ns3/helper-module.h"
 
-#include "ns3/ascii-trace.h"
-#include "ns3/pcap-trace.h"
-
 using namespace ns3;
 
 NS_LOG_COMPONENT_DEFINE ("CsmaPacketSocketExample");
@@ -105,9 +102,9 @@
   // Configure tracing of all enqueue, dequeue, and NetDevice receive events
   // Trace output will be sent to the csma-packet-socket.tr file
   NS_LOG_INFO ("Configure Tracing.");
-  AsciiTrace asciitrace ("csma-packet-socket.tr");
-  asciitrace.TraceAllNetDeviceRx ();
-  asciitrace.TraceAllQueues ();
+  std::ofstream os;
+  os.open ("csma-packet-socket.tr");
+  csma.EnableAsciiAll (os);
 
   NS_LOG_INFO ("Run Simulation.");
   Simulator::Run ();
--- a/examples/mixed-global-routing.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/mixed-global-routing.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -40,8 +40,6 @@
 #include "ns3/simulator-module.h"
 #include "ns3/node-module.h"
 #include "ns3/helper-module.h"
-#include "ns3/ascii-trace.h"
-#include "ns3/pcap-trace.h"
 #include "ns3/global-route-manager.h"
 
 using namespace ns3;
@@ -73,13 +71,13 @@
   // We create the channels first without any IP addressing information
   NS_LOG_INFO ("Create channels.");
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
   NetDeviceContainer d0d2 = p2p.Install (n0n2);
 
   NetDeviceContainer d1d2 = p2p.Install (n1n2);
 
-  p2p.SetChannelParameter ("BitRate", StringValue ("1500kbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
   NetDeviceContainer d5d6 = p2p.Install (n5n6);
 
--- a/examples/mixed-wireless.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/mixed-wireless.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -159,8 +159,12 @@
   MobilityHelper mobility;
   Ptr<ListPositionAllocator> positionAlloc = 
     CreateObject<ListPositionAllocator> ();
-  positionAlloc->Add (Vector (0.0, 0.0, 0.0));
-  positionAlloc->Add (Vector (5.0, 0.0, 0.0));
+  double x = 0.0;
+  for (uint32_t i = 0; i < backboneNodes; ++i)
+    {
+      positionAlloc->Add (Vector (x, 0.0, 0.0));
+      x += 5.0;
+    }
   mobility.SetPositionAllocator (positionAlloc);
   mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
                              "Bounds", RectangleValue (Rectangle (0, 1000, 0, 1000)),
@@ -268,7 +272,6 @@
         {
           subnetAlloc->Add (Vector (0.0, j, 0.0));
         }
-      mobility.EnableNotifier ();
       mobility.PushReferenceMobilityModel (backbone.Get (i));
       mobility.SetPositionAllocator (subnetAlloc);
       mobility.SetMobilityModel ("ns3::RandomDirection2dMobilityModel",
@@ -329,14 +332,13 @@
   //
   // Let's set up some ns-2-like ascii traces, using another helper class
   //
-  // Look at nodes 11, 13 only
-  // XXX todo
-  // asciiTrace.TraceQueues ("/NodeList/11|13/DeviceList/0");
-  // asciiTrace.TraceNetDeviceRx ("/NodeList/11|13/DeviceList/0");
   std::ofstream ascii;
   ascii.open ("mixed-wireless.tr");
   WifiHelper::EnableAsciiAll (ascii);
   CsmaHelper::EnableAsciiAll (ascii);
+  // Look at nodes 11, 13 only
+  //WifiHelper::EnableAscii (ascii, 11, 0); 
+  //WifiHelper::EnableAscii (ascii, 13, 0); 
 
   // Let's do a pcap trace on the backbone devices
   WifiHelper::EnablePcap ("mixed-wireless", backboneDevices); 
@@ -344,10 +346,11 @@
   CsmaHelper::EnablePcap ("mixed-wireless", appSink->GetId (), 0);
 
 #ifdef ENABLE_FOR_TRACING_EXAMPLE
-  Config::Connect ("/NodeList/*/$MobilityModelNotifier/CourseChange",
+  Config::Connect ("/NodeList/*/$MobilityModel/CourseChange",
     MakeCallback (&CourseChangeCallback));
 #endif
 
+
   /////////////////////////////////////////////////////////////////////////// 
   //                                                                       //
   // Run simulation                                                        //
@@ -355,7 +358,7 @@
   /////////////////////////////////////////////////////////////////////////// 
 
   NS_LOG_INFO ("Run Simulation.");
-  Simulator::StopAt (Seconds (stopTime));
+  Simulator::Stop (Seconds (stopTime));
   Simulator::Run ();    
   Simulator::Destroy ();
 }
--- a/examples/simple-alternate-routing.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/simple-alternate-routing.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -97,13 +97,13 @@
   // We create the channels first without any IP addressing information
   NS_LOG_INFO ("Create channels.");
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
   NetDeviceContainer d0d2 = p2p.Install (n0n2);
 
   NetDeviceContainer d1d2 = p2p.Install (n1n2);
 
-  p2p.SetChannelParameter ("BitRate", StringValue ("1500kbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
   NetDeviceContainer d3d2 = p2p.Install (n3n2);
 
--- a/examples/simple-error-model.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/simple-error-model.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -92,13 +92,13 @@
   // We create the channels first without any IP addressing information
   NS_LOG_INFO ("Create channels.");
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", DataRateValue (DataRate (5000000)));
+  p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate (5000000)));
   p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds (2)));
   NetDeviceContainer d0d2 = p2p.Install (n0n2);
 
   NetDeviceContainer d1d2 = p2p.Install (n1n2);
 
-  p2p.SetChannelParameter ("BitRate", DataRateValue (DataRate (1500000)));
+  p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate (1500000)));
   p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds (10)));
   NetDeviceContainer d3d2 = p2p.Install (n3n2);
   
--- a/examples/simple-global-routing.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/simple-global-routing.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -92,13 +92,13 @@
   // We create the channels first without any IP addressing information
   NS_LOG_INFO ("Create channels.");
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
   NetDeviceContainer d0d2 = p2p.Install (n0n2);
 
   NetDeviceContainer d1d2 = p2p.Install (n1n2);
   
-  p2p.SetChannelParameter ("BitRate", StringValue ("1500kbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
   NetDeviceContainer d3d2 = p2p.Install (n3n2);
   
--- a/examples/simple-point-to-point-olsr.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/simple-point-to-point-olsr.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -93,11 +93,11 @@
   // We create the channels first without any IP addressing information
   NS_LOG_INFO ("Create channels.");
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", StringValue ("5Mbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("5Mbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("2ms"));
   NetDeviceContainer nd02 = p2p.Install (n02);
   NetDeviceContainer nd12 = p2p.Install (n12);
-  p2p.SetChannelParameter ("BitRate", StringValue ("1500kbps"));
+  p2p.SetDeviceParameter ("DataRate", StringValue ("1500kbps"));
   p2p.SetChannelParameter ("Delay", StringValue ("10ms"));
   NetDeviceContainer nd32 = p2p.Install (n32);
   NetDeviceContainer nd34 = p2p.Install (n34);
@@ -161,7 +161,7 @@
   PointToPointHelper::EnablePcapAll ("simple-point-to-point-olsr");
   PointToPointHelper::EnableAsciiAll (ascii);
 
-  Simulator::StopAt (Seconds (30));
+  Simulator::Stop (Seconds (30));
 
   NS_LOG_INFO ("Run Simulation.");
   Simulator::Run ();
--- a/examples/tcp-large-transfer.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/tcp-large-transfer.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -111,7 +111,7 @@
 
   // We create the channels first without any IP addressing information
   PointToPointHelper p2p;
-  p2p.SetChannelParameter ("BitRate", DataRateValue (DataRate(100000)));
+  p2p.SetDeviceParameter ("DataRate", DataRateValue (DataRate(10000000)));
   p2p.SetChannelParameter ("Delay", TimeValue (MilliSeconds(10)));
   NetDeviceContainer dev0 = p2p.Install (c0);
   NetDeviceContainer dev1 = p2p.Install (c1);
@@ -165,7 +165,7 @@
 
   PointToPointHelper::EnablePcapAll ("tcp-large-transfer");
 
-  Simulator::StopAt (Seconds(100));
+  Simulator::Stop (Seconds(1000));
   Simulator::Run ();
   Simulator::Destroy ();
 }
--- a/examples/wifi-adhoc.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/wifi-adhoc.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -102,7 +102,7 @@
 Ptr<Socket>
 Experiment::SetupPacketReceive (Ptr<Node> node)
 {
-  TypeId tid = TypeId::LookupByName ("ns3::PacketSocket");
+  TypeId tid = TypeId::LookupByName ("ns3::PacketSocketFactory");
   Ptr<Socket> sink = Socket::CreateSocket (node, tid);
   sink->Bind ();
   sink->SetRecvCallback (MakeCallback (&Experiment::ReceivePacket, this));
@@ -136,7 +136,7 @@
   socket.SetPhysicalAddress (devices.Get (1)->GetAddress ());
   socket.SetProtocol (1);
 
-  OnOffHelper onoff ("ns3::PacketSocket", Address (socket));
+  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (250)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
   onoff.SetAttribute ("DataRate", DataRateValue (DataRate (60000000)));
--- a/examples/wifi-ap.cc	Fri May 30 15:31:50 2008 -0400
+++ b/examples/wifi-ap.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -162,7 +162,7 @@
   socket.SetPhysicalAddress (staDevs.Get (1)->GetAddress ());
   socket.SetProtocol (1);
 
-  OnOffHelper onoff ("ns3::PacketSocket", Address (socket));
+  OnOffHelper onoff ("ns3::PacketSocketFactory", Address (socket));
   onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (42)));
   onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
 
@@ -170,7 +170,7 @@
   apps.Start (Seconds (0.5));
   apps.Stop (Seconds (43.0));
 
-  Simulator::StopAt (Seconds (44.0));
+  Simulator::Stop (Seconds (44.0));
 
   Config::Connect ("/NodeList/*/DeviceList/*/Tx", MakeCallback (&DevTxTrace));
   Config::Connect ("/NodeList/*/DeviceList/*/Rx", MakeCallback (&DevRxTrace));
--- a/samples/main-packet-tag.cc	Fri May 30 15:31:50 2008 -0400
+++ b/samples/main-packet-tag.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -19,6 +19,7 @@
  */
 #include "ns3/tag.h"
 #include "ns3/packet.h"
+#include "ns3/uinteger.h"
 #include <iostream>
 
 using namespace ns3;
@@ -27,22 +28,12 @@
 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);
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
   
   // these are our accessors to our tag structure
   void SetSimpleValue (uint8_t value);
@@ -51,53 +42,46 @@
   uint8_t m_simpleValue;
 };
 
-MyTag::MyTag ()
-{}
-MyTag::MyTag (const MyTag &other)
-  : m_simpleValue (other.m_simpleValue)
-{}
-MyTag::~MyTag ()
-{}
+TypeId 
+MyTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::MyTag")
+    .SetParent<Tag> ()
+    .AddConstructor<MyTag> ()
+    .AddAttribute ("SimpleValue",
+                   "A simple value",
+                   EmptyAttributeValue (),
+                   MakeUintegerAccessor (&MyTag::GetSimpleValue),
+                   MakeUintegerChecker<uint8_t> ())
+    ;
+  return tid;
+}
+TypeId 
+MyTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
 uint32_t 
-MyTag::GetUid (void)
+MyTag::GetSerializedSize (void) const
+{
+  return 1;
+}
+void 
+MyTag::Serialize (TagBuffer i) const
 {
-  // we input a unique string to AllocateUid
-  // to avoid name collisions.
-  static uint32_t uid = AllocateUid<MyTag> ("MyTag.tests.nsnam.org");
-  return uid;
+  i.WriteU8 (m_simpleValue);
+}
+void 
+MyTag::Deserialize (TagBuffer i)
+{
+  m_simpleValue = i.ReadU8 ();
 }
 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;
+  os << "v=" << (uint32_t)m_simpleValue;
 }
 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;
@@ -116,7 +100,7 @@
   tag.SetSimpleValue (0x56);
 
   // store the tag in a packet.
-  Ptr<Packet> p = Create<Packet> ();
+  Ptr<Packet> p = Create<Packet> (100);
   p->AddTag (tag);
 
   // create a copy of the packet
@@ -124,7 +108,7 @@
 
   // read the tag from the packet copy
   MyTag tagCopy;
-  p->PeekTag (tagCopy);
+  p->FindFirstMatchingTag (tagCopy);
 
   // the copy and the original are the same !
   NS_ASSERT (tagCopy.GetSimpleValue () == tag.GetSimpleValue ());
--- a/samples/main-random-topology.cc	Fri May 30 15:31:50 2008 -0400
+++ b/samples/main-random-topology.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -25,7 +25,6 @@
   c.Create (10000);
 
   MobilityHelper mobility;
-  mobility.EnableNotifier ();
   mobility.SetPositionAllocator ("ns3::RandomDiscPositionAllocator",
                                  "X", StringValue ("100.0"),
                                  "Y", StringValue ("100.0"),
@@ -36,7 +35,7 @@
   Config::Connect ("/NodeList/*/$ns3::MobilityModelNotifier/CourseChange",
                               MakeCallback (&CourseChange));
   
-  Simulator::StopAt (Seconds (100.0));
+  Simulator::Stop (Seconds (100.0));
 
   Simulator::Run ();
   
--- a/samples/main-random-walk.cc	Fri May 30 15:31:50 2008 -0400
+++ b/samples/main-random-walk.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -8,7 +8,7 @@
 using namespace ns3;
 
 static void 
-CourseChange (ns3::TraceContext const&, Ptr<const MobilityModel> mobility)
+CourseChange (std::string foo, Ptr<const MobilityModel> mobility)
 {
   Vector pos = mobility->GetPosition ();
   Vector vel = mobility->GetVelocity ();
@@ -22,7 +22,7 @@
   Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Mode", StringValue ("Time"));
   Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Time", StringValue ("2s"));
   Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Speed", StringValue ("Constant:1.0"));
-  Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Bounds", StringValue ("0:200:0:100"));
+  Config::SetDefault ("ns3::RandomWalk2dMobilityModel::Bounds", StringValue ("0|200|0|200"));
 
   CommandLine cmd;
   cmd.Parse (argc, argv);
@@ -31,7 +31,6 @@
   c.Create (100);
 
   MobilityHelper mobility;
-  mobility.EnableNotifier ();
   mobility.SetPositionAllocator ("ns3::RandomDiscPositionAllocator",
                                  "X", StringValue ("100.0"),
                                  "Y", StringValue ("100.0"),
@@ -40,12 +39,12 @@
                              "Mode", StringValue ("Time"),
                              "Time", StringValue ("2s"),
                              "Speed", StringValue ("Constant:1.0"),
-                             "Bounds", StringValue ("0:200:0:100"));
+                             "Bounds", StringValue ("0|200|0|200"));
   mobility.InstallAll ();
-  Config::Connect ("/NodeList/*/$ns3::MobilityModelNotifier/CourseChange",
+  Config::Connect ("/NodeList/*/$ns3::MobilityModel/CourseChange",
                    MakeCallback (&CourseChange));
 
-  Simulator::StopAt (Seconds (100.0));
+  Simulator::Stop (Seconds (100.0));
 
   Simulator::Run ();
   
--- a/src/applications/packet-sink/packet-sink.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/applications/packet-sink/packet-sink.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -106,10 +106,11 @@
   while (packet = socket->Recv ())
     {
       SocketRxAddressTag tag;
-      bool found = packet->PeekTag (tag);
+      bool found;
+      found = packet->FindFirstMatchingTag (tag);
       NS_ASSERT (found);
       Address from = tag.GetAddress ();
-      packet->RemoveTag (tag);
+      // XXX packet->RemoveTag (tag);
       if (InetSocketAddress::IsMatchingType (from))
         {
           InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
--- a/src/applications/udp-echo/udp-echo-client.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/applications/udp-echo/udp-echo-client.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -93,7 +93,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  if (!m_socket)
+  if (m_socket == 0)
     {
       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
       m_socket = Socket::CreateSocket (GetNode(), tid);
@@ -111,7 +111,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  if (!m_socket) 
+  if (m_socket != 0) 
     {
       m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
     }
@@ -153,10 +153,11 @@
   while (packet = socket->Recv ())
     {
       SocketRxAddressTag tag;
-      bool found = packet->PeekTag (tag);
+      bool found;
+      found  = packet->FindFirstMatchingTag (tag);
       NS_ASSERT (found);
       Address from = tag.GetAddress ();
-      packet->RemoveTag (tag);
+      // XXX packet->RemoveTag (tag);
       if (InetSocketAddress::IsMatchingType (from))
         {
           InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
--- a/src/applications/udp-echo/udp-echo-server.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/applications/udp-echo/udp-echo-server.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -69,7 +69,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  if (!m_socket)
+  if (m_socket == 0)
     {
       TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
       m_socket = Socket::CreateSocket (GetNode(), tid);
@@ -85,7 +85,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  if (!m_socket) 
+  if (m_socket != 0) 
     {
       m_socket->SetRecvCallback(MakeNullCallback<void, Ptr<Socket> > ());
     }
@@ -98,10 +98,11 @@
   while (packet = socket->Recv ())
     {
       SocketRxAddressTag tag;
-      bool found = packet->PeekTag (tag); 
+      bool found;
+      found = packet->FindFirstMatchingTag (tag); 
       NS_ASSERT (found);
       Address from = tag.GetAddress ();
-      packet->RemoveTag (tag);
+      // XXX packet->RemoveTag (tag);
       if (InetSocketAddress::IsMatchingType (from))
         {
           InetSocketAddress address = InetSocketAddress::ConvertFrom (from);
--- a/src/common/buffer.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/buffer.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -203,11 +203,13 @@
 
 Buffer::Buffer ()
 {
+  NS_LOG_FUNCTION (this);
   Initialize (0);
 }
 
 Buffer::Buffer (uint32_t dataSize)
 {
+  NS_LOG_FUNCTION (this << dataSize);
   Initialize (dataSize);
 }
 
@@ -225,17 +227,21 @@
     m_start <= m_data->m_size &&
     m_zeroAreaStart <= m_data->m_size;
 
-  NS_ASSERT (offsetsOk);
-  NS_ASSERT (dirtyOk);
-  NS_ASSERT (internalSizeOk);
-
-  return m_data->m_count > 0 && offsetsOk && dirtyOk && 
-    internalSizeOk;
+  bool ok = m_data->m_count > 0 && offsetsOk && dirtyOk && internalSizeOk;
+  if (!ok)
+    {
+      LOG_INTERNAL_STATE ("check " << this << 
+                          ", " << (offsetsOk?"true":"false") << 
+                          ", " << (dirtyOk?"true":"false") << 
+                          ", " << (internalSizeOk?"true":"false") << " ");
+    }
+  return ok;
 }
 
 void
 Buffer::Initialize (uint32_t zeroSize)
 {
+  NS_LOG_FUNCTION (this << zeroSize);
   m_data = Buffer::Create (0);
 #ifdef BUFFER_HEURISTICS
   m_start = std::min (m_data->m_size, g_recommendedStart);
@@ -261,6 +267,7 @@
     m_start (o.m_start),
     m_end (o.m_end)
 {
+  NS_LOG_FUNCTION (this << &o);
   m_data->m_count++;
   NS_ASSERT (CheckInternalState ());
 }
@@ -268,6 +275,7 @@
 Buffer &
 Buffer::operator = (Buffer const&o)
 {
+  NS_LOG_FUNCTION (this << &o);
   NS_ASSERT (CheckInternalState ());
   if (m_data != o.m_data) 
     {
@@ -294,6 +302,8 @@
 
 Buffer::~Buffer ()
 {
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT (CheckInternalState ());
   HEURISTICS (g_recommendedStart = std::max (g_recommendedStart, m_maxZeroAreaStart));
   m_data->m_count--;
   if (m_data->m_count == 0) 
@@ -333,9 +343,11 @@
   return m_end - (m_zeroAreaEnd - m_zeroAreaStart);
 }
 
-void 
+bool
 Buffer::AddAtStart (uint32_t start)
 {
+  NS_LOG_FUNCTION (this << start);
+  bool dirty;
   NS_ASSERT (CheckInternalState ());
   bool isDirty = m_data->m_count > 1 && m_start > m_data->m_dirtyStart;
   if (m_start >= start && !isDirty)
@@ -347,31 +359,13 @@
        */
       NS_ASSERT (m_data->m_count == 1 || m_start == m_data->m_dirtyStart);
       m_start -= start;
+      dirty = m_start > m_data->m_dirtyStart;
+      // update dirty area
+      m_data->m_dirtyStart = m_start;
       HEURISTICS (g_nAddNoRealloc++);
     } 
-#if 0
-  // the following is an optimization
-  else if (m_start >= start)
-    {
-      struct BufferData *newData = Buffer::Create (m_data->m_size);
-      memcpy (newData->m_data + m_start, m_data->m_data + m_start, GetInternalSize ());
-      m_data->m_count--;
-      if (m_data->m_count == 0)
-        {
-          Buffer::Recycle (m_data);
-        }
-      m_data = newData;
-
-      m_start -= start;
-      HEURISTICS (g_nAddRealloc++);
-    }
   else
     {
-      NS_ASSERT (m_start < start);
-#else
-  else
-    {
-#endif
       uint32_t newSize = GetInternalSize () + start;
       struct BufferData *newData = Buffer::Create (newSize);
       memcpy (newData->m_data + start, m_data->m_data + m_start, GetInternalSize ());
@@ -383,23 +377,30 @@
       m_data = newData;
 
       int32_t delta = start - m_start;
-      m_start = 0;
+      m_start += delta;
       m_zeroAreaStart += delta;
       m_zeroAreaEnd += delta;
       m_end += delta;
+      m_start -= start;
+
+      // update dirty area
+      m_data->m_dirtyStart = m_start;
+      m_data->m_dirtyEnd = m_end;
+
+      dirty = true;
 
       HEURISTICS (g_nAddRealloc++);
     }
   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
-  // update dirty area
-  m_data->m_dirtyStart = m_start;
-  m_data->m_dirtyEnd = m_end;
   LOG_INTERNAL_STATE ("add start=" << start << ", ");
   NS_ASSERT (CheckInternalState ());
+  return dirty;
 }
-void 
+bool
 Buffer::AddAtEnd (uint32_t end)
 {
+  NS_LOG_FUNCTION (this << end);
+  bool dirty;
   NS_ASSERT (CheckInternalState ());
   bool isDirty = m_data->m_count > 1 && m_end < m_data->m_dirtyEnd;
   if (GetInternalEnd () + end <= m_data->m_size && !isDirty)
@@ -411,26 +412,13 @@
        */
       NS_ASSERT (m_data->m_count == 1 || m_end == m_data->m_dirtyEnd);
       m_end += end;
+      // update dirty area.
+      m_data->m_dirtyEnd = m_end;
+
+      dirty = m_end < m_data->m_dirtyEnd;
 
       HEURISTICS (g_nAddNoRealloc++);
     } 
-#if 0
-  // this is an optimization
-  else if (GetInternalEnd () + end > m_data->m_size)
-    {
-      struct BufferData *newData = Buffer::Create (newSize);
-      memcpy (newData->m_data + m_start, m_data->m_data + m_start, GetInternalSize ());
-      m_data->m_count--;
-      if (m_data->m_count == 0) 
-        {
-          Buffer::Recycle (m_data);
-        }
-      m_data = newData;
-
-      m_end += end;
-      HEURISTICS (g_nAddRealloc++);
-    }
-#endif
   else
     {
       uint32_t newSize = GetInternalSize () + end;
@@ -443,28 +431,35 @@
         }
       m_data = newData;
 
+      int32_t delta = -m_start;
+      m_zeroAreaStart += delta;
+      m_zeroAreaEnd += delta;
+      m_end += delta;
+      m_start += delta;
+      m_end += end;
 
-      m_zeroAreaStart -= m_start;
-      m_zeroAreaEnd -= m_start;
-      m_end -= m_start;
-      m_start = 0;
+      // update dirty area
+      m_data->m_dirtyStart = m_start;
+      m_data->m_dirtyEnd = m_end;
 
-      m_end += end;
+      dirty = true;
 
       HEURISTICS (g_nAddRealloc++);
     } 
   HEURISTICS (m_maxZeroAreaStart = std::max (m_maxZeroAreaStart, m_zeroAreaStart));
-  // update dirty area
-  m_data->m_dirtyStart = m_start;
-  m_data->m_dirtyEnd = m_end;
   LOG_INTERNAL_STATE ("add end=" << end << ", ");
   NS_ASSERT (CheckInternalState ());
+
+  return dirty;
 }
 
-void 
+void
 Buffer::AddAtEnd (const Buffer &o)
 {
-  if (m_end == m_zeroAreaEnd &&
+  NS_LOG_FUNCTION (this << &o);
+  if (m_data->m_count == 1 &&
+      m_end == m_zeroAreaEnd &&
+      m_end == m_data->m_dirtyEnd &&
       o.m_start == o.m_zeroAreaStart &&
       o.m_zeroAreaEnd - o.m_zeroAreaStart > 0)
     {
@@ -476,6 +471,7 @@
       uint32_t zeroSize = o.m_zeroAreaEnd - o.m_zeroAreaStart;
       m_zeroAreaEnd += zeroSize;
       m_end = m_zeroAreaEnd;
+      m_data->m_dirtyEnd = m_zeroAreaEnd;
       uint32_t endData = o.m_end - o.m_zeroAreaEnd;
       AddAtEnd (endData);
       Buffer::Iterator dst = End ();
@@ -483,8 +479,10 @@
       Buffer::Iterator src = o.End ();
       src.Prev (endData);
       dst.Write (src, o.End ());
+      NS_ASSERT (CheckInternalState ());
       return;
     }
+
   Buffer dst = CreateFullCopy ();
   Buffer src = o.CreateFullCopy ();
 
@@ -493,11 +491,13 @@
   destStart.Prev (src.GetSize ());
   destStart.Write (src.Begin (), src.End ());
   *this = dst;
+  NS_ASSERT (CheckInternalState ());
 }
 
 void 
 Buffer::RemoveAtStart (uint32_t start)
 {
+  NS_LOG_FUNCTION (this << start);
   NS_ASSERT (CheckInternalState ());
   uint32_t newStart = m_start + start;
   if (newStart <= m_zeroAreaStart)
@@ -542,6 +542,7 @@
 void 
 Buffer::RemoveAtEnd (uint32_t end)
 {
+  NS_LOG_FUNCTION (this << end);
   NS_ASSERT (CheckInternalState ());
   uint32_t newEnd = m_end - std::min (end, m_end - m_start);
   if (newEnd > m_zeroAreaEnd)
@@ -577,6 +578,7 @@
 Buffer 
 Buffer::CreateFragment (uint32_t start, uint32_t length) const
 {
+  NS_LOG_FUNCTION (this << start << length);
   NS_ASSERT (CheckInternalState ());
   Buffer tmp = *this;
   tmp.RemoveAtStart (start);
@@ -588,6 +590,7 @@
 Buffer 
 Buffer::CreateFullCopy (void) const
 {
+  NS_LOG_FUNCTION (this);
   NS_ASSERT (CheckInternalState ());
   if (m_zeroAreaEnd - m_zeroAreaStart != 0) 
     {
@@ -602,12 +605,25 @@
       Buffer::Iterator i = tmp.End ();
       i.Prev (dataEnd);
       i.Write (m_data->m_data+m_zeroAreaStart,dataEnd);
+      NS_ASSERT (tmp.CheckInternalState ());
       return tmp;
     }
   NS_ASSERT (CheckInternalState ());
   return *this;
 }
 
+int32_t 
+Buffer::GetCurrentStartOffset (void) const
+{
+  return m_start;
+}
+int32_t 
+Buffer::GetCurrentEndOffset (void) const
+{
+  return m_end;
+}
+
+
 void
 Buffer::TransformIntoRealBuffer (void) const
 {
--- a/src/common/buffer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/buffer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -36,6 +36,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup packet
+ *
  * \brief automatically resized byte buffer
  *
  * This represents a buffer of bytes. Its size is
@@ -392,6 +394,7 @@
 
   /**
    * \param start size to reserve
+   * \returns true if the buffer needed resizing, false otherwise.
    *
    * Add bytes at the start of the Buffer. The
    * content of these bytes is undefined but debugging
@@ -399,9 +402,10 @@
    * Any call to this method invalidates any Iterator
    * pointing to this Buffer.
    */
-  void AddAtStart (uint32_t start);
+  bool AddAtStart (uint32_t start);
   /**
    * \param end size to reserve
+   * \returns true if the buffer needed resizing, false otherwise.
    *
    * Add bytes at the end of the Buffer. The
    * content of these bytes is undefined but debugging
@@ -409,8 +413,15 @@
    * Any call to this method invalidates any Iterator
    * pointing to this Buffer.
    */
-  void AddAtEnd (uint32_t end);
+  bool AddAtEnd (uint32_t end);
 
+  /**
+   * \param o the buffer to append to the end of this buffer.
+   *
+   * Add bytes at the end of the Buffer.
+   * Any call to this method invalidates any Iterator
+   * pointing to this Buffer.
+   */
   void AddAtEnd (const Buffer &o);
   /**
    * \param start size to remove
@@ -451,6 +462,9 @@
 
   Buffer CreateFullCopy (void) const;
 
+  int32_t GetCurrentStartOffset (void) const;
+  int32_t GetCurrentEndOffset (void) const;
+
   Buffer (Buffer const &o);
   Buffer &operator = (Buffer const &o);
   Buffer ();
--- a/src/common/chunk.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/chunk.h	Wed Jun 04 17:19:32 2008 -0400
@@ -6,6 +6,11 @@
 
 namespace ns3 {
 
+/**
+ * \ingroup packet
+ *
+ * \brief abstract base class for ns3::Header and ns3::Trailer
+ */
 class Chunk : public ObjectBase
 {
  public:
--- a/src/common/data-rate.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/data-rate.h	Wed Jun 04 17:19:32 2008 -0400
@@ -31,6 +31,11 @@
 namespace ns3 {
 
 /**
+ * \ingroup common
+ * \defgroup datarate Data Rate
+ */
+/**
+ * \ingroup datarate
  * \brief Class for representing data rates
  *
  * Allows for natural and familiar use of data rates.  Allows construction
@@ -80,7 +85,6 @@
    */
   uint64_t GetBitRate() const;
 
-  ATTRIBUTE_HELPER_HEADER_1 (DataRate);
 private:
   uint64_t m_bps;
   static uint64_t Parse(const std::string);
@@ -94,7 +98,7 @@
  * \brief hold objects of type ns3::DataRate
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (DataRate);
+ATTRIBUTE_HELPER_HEADER (DataRate);
 
 /**
  * \param lhs
--- a/src/common/data-writer.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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 "data-writer.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/poll.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "ns3/assert.h"
-#include <string.h>
-#include <list>
-
-#define noTRACE_DATA_WRITER 1
-
-#ifdef TRACE_DATA_WRITER
-#include <iostream>
-# define TRACE(x) \
-std::cout << "DATA WRITER TRACE " << this << " " << x << std::endl;
-#else /* TRACE_DATA_WRITER */
-# define TRACE(format,...)
-#endif /* TRACE_DATA_WRITER */
-
-#define BUFFER_SIZE (4096)
-
-
-namespace ns3 {
-
-class DataWriterPrivate {
-public:
-  DataWriterPrivate ();
-  ~DataWriterPrivate ();
-
-  void open (char const *filename);
-  void write (uint8_t *buffer, uint32_t size);
-private:
-  uint8_t m_data[BUFFER_SIZE];
-  uint32_t m_current;
-  int m_fd;
-};
-
-DataWriterPrivate::DataWriterPrivate ()
-  : m_current (0)
-{}
-DataWriterPrivate::~DataWriterPrivate ()
-{
-  ::Write (m_fd, m_data, m_current);
-  ::Close (m_fd);
-}
-
-
-void
-DataWriterPrivate::Open (char const *filename)
-{
-  m_fd = ::Open (filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
-  NS_ASSERT (m_fd != -1);
-}
-
-#ifndef min
-#define min(a,b) ((a)<(b)?(a):(b))
-#endif /* min */
-
-void
-DataWriterPrivate::Write (uint8_t *buffer, uint32_t size)
-{
-  while (size > 0) 
-    {
-      uint32_t toCopy = min (BUFFER_SIZE - m_current, size);
-      memcpy (m_data + m_current, buffer, toCopy);
-      size -= toCopy;
-      m_current += toCopy;
-      buffer += toCopy;
-      if (m_current == BUFFER_SIZE) 
-        {
-          ssize_t written = 0;
-          written = ::Write (m_fd, m_data, BUFFER_SIZE);
-          NS_ASSERT (written == BUFFER_SIZE);
-          m_current = 0;
-        }
-    }
-}
-
-DataWriter::DataWriter ()
-  : m_priv (new DataWriterPrivate ())
-{}
-DataWriter::~DataWriter ()
-{
-  delete m_priv;
-  m_priv = 0;
-}
-
-void 
-DataWriter::Open (char const *filename)
-{
-  m_priv->Open (filename);
-}
-void 
-DataWriter::Write (uint8_t *buffer, uint32_t size)
-{
-  m_priv->Write (buffer, size);
-}
-
-}; // namespace
--- a/src/common/data-writer.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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>
- */
-
-#ifndef DATA_WRITER_H
-#define DATA_WRITER_H
-
-#include <stdint.h>
-
-namespace ns3 {
-
-class DataWriterPrivate;
-
-class DataWriter {
-public:
-  DataWriter ();
-  ~DataWriter ();
-
-  void open (char const *filename);
-  void write (uint8_t *buffer, uint32_t size);
-private:
-  DataWriterPrivate *m_priv;
-};
-
-}; //namespace ns3
-
-#endif /* DATA_WRITER_H */
--- a/src/common/error-model.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/error-model.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,11 @@
 class Packet;
 
 /**
+ * \ingroup common
+ * \defgroup errormodel Error Model
+ */
+/**
+ * \ingroup errormodel
  * \brief General error model that can be used to corrupt packets
  *
  * This object is used to flag packets as being lost/errored or not.
--- a/src/common/header.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/header.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,13 +28,13 @@
 namespace ns3 {
 
 /**
+ * \ingroup packet
+ *
  * \brief Protocol header serialization and deserialization.
  *
  * Every Protocol header which needs to be inserted or removed
  * 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.
+ * implement the pure virtual methods defined here. 
  *
  * 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
--- a/src/common/packet-metadata-test.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/packet-metadata-test.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -28,44 +28,74 @@
 #include "packet.h"
 #include "packet-metadata.h"
 
-namespace ns3 {
+using namespace ns3;
+
+namespace {
+
+class HistoryHeaderBase : public Header
+{
+public:
+  static TypeId GetTypeId (void);
+  HistoryHeaderBase ();
+  bool IsOk (void) const;
+protected:
+  void ReportError (void);
+private:
+  bool m_ok;
+};
+
+TypeId 
+HistoryHeaderBase::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::HistoryHeaderBase")
+    .SetParent<Header> ()
+    ;
+  return tid;
+}
+
+HistoryHeaderBase::HistoryHeaderBase ()
+  : m_ok (true)
+{}
+
+bool 
+HistoryHeaderBase::IsOk (void) const
+{
+  return m_ok;
+}
+void 
+HistoryHeaderBase::ReportError (void)
+{
+  m_ok = false;
+}
+
 
 template <int N>
-class HistoryHeader : public Header
+class HistoryHeader : public HistoryHeaderBase
 {
 public:
   HistoryHeader ();
-  bool IsOk (void) const;
   static TypeId GetTypeId (void);
   virtual TypeId GetInstanceTypeId (void) const;
   virtual void Print (std::ostream &os) const;
   virtual uint32_t GetSerializedSize (void) const;
   virtual void Serialize (Buffer::Iterator start) const;
   virtual uint32_t Deserialize (Buffer::Iterator start);
-private:
-  bool m_ok;
 };
 
 template <int N>
 HistoryHeader<N>::HistoryHeader ()
-  : m_ok (false)
+  : HistoryHeaderBase ()
 {}
 
 template <int N>
-bool 
-HistoryHeader<N>::IsOk (void) const
-{
-  return m_ok;
-}
-
-template <int N>
 TypeId
 HistoryHeader<N>::GetTypeId (void)
 {
   std::ostringstream oss;
   oss << "ns3::HistoryHeader<"<<N<<">";
   static TypeId tid = TypeId (oss.str ().c_str ())
-    .SetParent<Header> ()
+    .SetParent<HistoryHeaderBase> ()
+    .AddConstructor<HistoryHeader<N> > ()
     ;
   return tid;
 }
@@ -98,19 +128,53 @@
 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;
+          ReportError ();
         }
     }
   return N;
 }
 
+class HistoryTrailerBase : public Trailer
+{
+public:
+  static TypeId GetTypeId (void);
+  HistoryTrailerBase ();
+  bool IsOk (void) const;
+protected:
+  void ReportError (void);
+private:
+  bool m_ok;
+};
+
+TypeId 
+HistoryTrailerBase::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::HistoryTrailerBase")
+    .SetParent<Trailer> ()
+    ;
+  return tid;
+}
+HistoryTrailerBase::HistoryTrailerBase ()
+  : m_ok (true)
+{}
+bool 
+HistoryTrailerBase::IsOk (void) const
+{
+  return m_ok;
+}
+void 
+HistoryTrailerBase::ReportError (void)
+{
+  m_ok = false;
+}
+
+
 template <int N>
-class HistoryTrailer : public Trailer
+class HistoryTrailer : public HistoryTrailerBase
 {
 public:
   HistoryTrailer ();
@@ -128,24 +192,17 @@
 
 template <int N>
 HistoryTrailer<N>::HistoryTrailer ()
-  : m_ok (false)
 {}
 
 template <int N>
-bool
-HistoryTrailer<N>::IsOk (void) const
-{
-  return m_ok;
-}
-
-template <int N>
 TypeId
 HistoryTrailer<N>::GetTypeId (void)
 {
   std::ostringstream oss;
   oss << "ns3::HistoryTrailer<"<<N<<">";
   static TypeId tid = TypeId (oss.str ().c_str ())
-    .SetParent<Trailer> ()
+    .SetParent<HistoryTrailerBase> ()
+    .AddConstructor<HistoryTrailer<N> > ()
     ;
   return tid;
 }
@@ -179,18 +236,21 @@
 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;
+          ReportError ();
         }
     }
   return N;
 }
 
+}
+
+namespace ns3 {
+
 
 
 class PacketMetadataTest : public Test {
@@ -228,6 +288,43 @@
   while (k.HasNext ())
     {
       struct PacketMetadata::Item item = k.Next ();
+      if (item.isFragment || item.type == PacketMetadata::Item::PAYLOAD)
+        {
+          got.push_back (item.currentSize);
+          continue;
+        }
+      if (item.type == PacketMetadata::Item::HEADER)
+        {
+          Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
+          HistoryHeaderBase *header = dynamic_cast<HistoryHeaderBase *> (constructor ());
+          if (header == 0)
+            {
+              goto error;
+            }
+          header->Deserialize (item.current);
+          if (!header->IsOk ())
+            {
+              delete header;
+              goto error;
+            }
+          delete header;
+        }
+      else if (item.type == PacketMetadata::Item::TRAILER)
+        {
+          Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
+          HistoryTrailerBase *trailer = dynamic_cast<HistoryTrailerBase *> (constructor ());
+          if (trailer == 0)
+            {
+              goto error;
+            }
+          trailer->Deserialize (item.current);
+          if (!trailer->IsOk ())
+            {
+              delete trailer;
+              goto error;
+            }
+          delete trailer;
+        }
       got.push_back (item.currentSize);
     }
 
@@ -285,7 +382,7 @@
     if (!CheckHistory (p, __FILE__,             \
                       __LINE__, __VA_ARGS__))   \
       {                                         \
-        ok = false;                             \
+        result = false;                         \
       }                                         \
     Buffer buffer;                              \
     buffer = p->Serialize ();                   \
@@ -294,7 +391,7 @@
     if (!CheckHistory (otherPacket, __FILE__,   \
                       __LINE__, __VA_ARGS__))   \
       {                                         \
-        ok = false;                             \
+        result = false;                         \
       }                                         \
   }
 
@@ -309,7 +406,7 @@
 bool
 PacketMetadataTest::RunTests (void)
 {
-  bool ok = true;
+  bool result = true;
 
   PacketMetadata::Enable ();
 
@@ -607,7 +704,55 @@
   p = Create<Packet> (16383);
   p = Create<Packet> (16384);
 
-  return ok;
+
+  // bug 179.
+  p = Create<Packet> (40);
+  p2 = p->CreateFragment (5, 5);
+  p3 = p->CreateFragment (10, 30);
+  ADD_HEADER (p2, 8);
+  ADD_HEADER (p3, 8);
+  REM_HEADER (p2, 8);
+  REM_HEADER (p3, 8);
+  p2->AddAtEnd (p3);
+
+
+  p = Create<Packet> (1000);
+  ADD_HEADER (p, 10);
+  ADD_TRAILER (p, 5);
+  p1 = p->Copy ();
+  ADD_HEADER (p1, 20);
+  REM_HEADER (p1, 20);
+  REM_TRAILER (p1, 5);
+  NS_TEST_ASSERT_EQUAL (p->GetSize (), 1015);
+
+  
+  p = Create<Packet> (1510);
+  ADD_HEADER (p, 8);
+  ADD_HEADER (p, 25);
+  REM_HEADER (p, 25);
+  ADD_HEADER (p, 1);
+  p1 = p->CreateFragment (0, 1500);
+  p2 = p1->Copy ();
+  ADD_HEADER (p2, 24);
+  NS_TEST_ASSERT_EQUAL (p->GetSize (), 1519);
+
+  p = Create<Packet> (1000);
+  ADD_HEADER (p, 2);
+  ADD_TRAILER (p, 3);
+  p1 = p->Copy ();
+  CHECK_HISTORY (p1, 3, 2, 1000, 3);
+  REM_HEADER (p, 2);
+  ADD_HEADER (p, 1);
+  CHECK_HISTORY (p, 3, 1, 1000, 3);
+  CHECK_HISTORY (p1, 3, 2, 1000, 3);
+
+  p = Create<Packet> (200);
+  ADD_HEADER (p, 24);
+  p1 = p->CreateFragment(0, 100);
+  p2 = p->CreateFragment(100, 100);	
+  p1->AddAtEnd (p2);
+
+  return result;
 }
 
 static PacketMetadataTest g_packetHistoryTest;
--- a/src/common/packet-metadata.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/packet-metadata.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -178,100 +178,13 @@
   value >>= 8;
   buffer[1] = value;
 }
-bool
-PacketMetadata::TryToAppend16 (uint16_t value,  uint8_t **pBuffer, uint8_t *end)
-{
-  uint8_t *start = *pBuffer;
-  if (start + 1 < end)
-    {
-      start[0] = value & 0xff;
-      start[1] = value >> 8;
-      *pBuffer = start + 2;
-      return true;
-    }
-  return false;
-}
-bool
-PacketMetadata::TryToAppend32 (uint32_t value,  uint8_t **pBuffer, uint8_t *end)
-{
-  uint8_t *start = *pBuffer;
-  if (start + 3 < end)
-    {
-      start[0] = value & 0xff;
-      start[1] = (value >> 8) & 0xff;
-      start[2] = (value >> 16) & 0xff;
-      start[3] = (value >> 24) & 0xff;
-      *pBuffer = start + 4;
-      return true;
-    }
-  return false;
-}
-bool
-PacketMetadata::TryToAppend (uint32_t value, uint8_t **pBuffer, uint8_t *end)
+void
+PacketMetadata::Append32 (uint32_t value,  uint8_t *buffer)
 {
-  uint8_t *start = *pBuffer;
-  if (value < 0x80 && start < end)
-    {
-      start[0] = value;
-      *pBuffer = start + 1;
-      return true;
-    }
-  if (value < 0x4000 && start + 1 < end)
-    {
-      uint8_t byte = value & (~0x80);
-      start[0] = 0x80 | byte;
-      value >>= 7;
-      start[1] = value;
-      *pBuffer = start + 2;
-      return true;
-    }
-  if (value < 0x200000 && start + 2 < end)
-    {
-      uint8_t byte = value & (~0x80);
-      start[0] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[1] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[2] = value;
-      *pBuffer = start + 3;
-      return true;
-    }
-  if (value < 0x10000000 && start + 3 < end)
-    {
-      uint8_t byte = value & (~0x80);
-      start[0] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[1] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[2] = 0x80 | byte;
-      value >>= 7;
-      start[3] = value;
-      *pBuffer = start + 4;
-      return true;
-    }
-  if (start + 4 < end)
-    {
-      uint8_t byte = value & (~0x80);
-      start[0] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[1] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[2] = 0x80 | byte;
-      value >>= 7;
-      byte = value & (~0x80);
-      start[3] = 0x80 | byte;
-      value >>= 7;
-      start[4] = value;
-      *pBuffer = start + 5;
-      return true;
-    }
-  return false;
+  buffer[0] = value & 0xff;
+  buffer[1] = (value >> 8) & 0xff;
+  buffer[2] = (value >> 16) & 0xff;
+  buffer[3] = (value >> 24) & 0xff;
 }
 
 void
@@ -342,6 +255,7 @@
 void
 PacketMetadata::UpdateTail (uint16_t written)
 {
+  NS_LOG_FUNCTION (this << written);
   if (m_head == 0xffff)
     {
       NS_ASSERT (m_tail == 0xffff);
@@ -368,6 +282,7 @@
 void
 PacketMetadata::UpdateHead (uint16_t written)
 {
+  NS_LOG_FUNCTION (this << written);
   if (m_head == 0xffff)
     {
       NS_ASSERT (m_tail == 0xffff);
@@ -393,33 +308,29 @@
 uint16_t
 PacketMetadata::AddSmall (const struct PacketMetadata::SmallItem *item)
 {
+  NS_LOG_FUNCTION (this << item->next << item->prev << item->typeUid << item->size << item->chunkUid);
   NS_ASSERT (m_data != 0);
   NS_ASSERT (m_used != item->prev && m_used != item->next);
   uint32_t typeUidSize = GetUleb128Size (item->typeUid);
   uint32_t sizeSize = GetUleb128Size (item->size);
-  uint32_t n = typeUidSize + sizeSize + 2 + 2 + 2;
- restart:
-  if (m_used + n <= m_data->m_size &&
-      (m_head == 0xffff ||
-       m_data->m_count == 1 ||
-       m_used == m_data->m_dirtyEnd))
-    {
-      uint8_t *buffer = &m_data->m_data[m_used];
-      Append16 (item->next, buffer);
-      buffer += 2;
-      Append16 (item->prev, buffer);
-      buffer += 2;
-      AppendValue (item->typeUid, buffer);
-      buffer += typeUidSize;
-      AppendValue (item->size, buffer);
-      buffer += sizeSize;
-      Append16 (item->chunkUid, buffer);
-    }
-  else
+  uint32_t n =  2 + 2 + typeUidSize + sizeSize + 2;
+  if (m_used + n > m_data->m_size ||
+      (m_head != 0xffff &&
+       m_data->m_count != 1 &&
+       m_used != m_data->m_dirtyEnd))
     {
       ReserveCopy (n);
-      goto restart;
     }
+  uint8_t *buffer = &m_data->m_data[m_used];
+  Append16 (item->next, buffer);
+  buffer += 2;
+  Append16 (item->prev, buffer);
+  buffer += 2;
+  AppendValue (item->typeUid, buffer);
+  buffer += typeUidSize;
+  AppendValue (item->size, buffer);
+  buffer += sizeSize;
+  Append16 (item->chunkUid, buffer);
   return n;
 }
 
@@ -428,76 +339,110 @@
                        const PacketMetadata::SmallItem *item, 
                        const PacketMetadata::ExtraItem *extraItem)
 {
+  NS_LOG_FUNCTION (this << next << prev <<  
+                   item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
+                   extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid);
   NS_ASSERT (m_data != 0);
   uint32_t typeUid = ((item->typeUid & 0x1) == 0x1)?item->typeUid:item->typeUid+1;
   NS_ASSERT (m_used != prev && m_used != next);
- append:
-  uint8_t *start = &m_data->m_data[m_used];
-  uint8_t *end = &m_data->m_data[m_data->m_size];
-  if (end - start >= 14 &&
-      (m_head == 0xffff ||
-       m_data->m_count == 1 ||
-       m_used == m_data->m_dirtyEnd))
-    {
-      uint8_t *buffer = start;
+
+  uint32_t typeUidSize = GetUleb128Size (typeUid);
+  uint32_t sizeSize = GetUleb128Size (item->size);
+  uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
+  uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
+  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
 
-      Append16 (next, buffer);
-      buffer += 2;
-      Append16 (prev, buffer);
-      buffer += 2;
-      if (TryToAppend (typeUid, &buffer, end) &&
-          TryToAppend (item->size, &buffer, end) &&
-          TryToAppend16 (item->chunkUid, &buffer, end) &&
-          TryToAppend (extraItem->fragmentStart, &buffer, end) &&
-          TryToAppend (extraItem->fragmentEnd, &buffer, end) &&
-          TryToAppend32 (extraItem->packetUid, &buffer, end))
-        {
-          uintptr_t written = buffer - start;
-          NS_ASSERT (written <= 0xffff);
-          NS_ASSERT (written >= 14);
-          return written;
-        }
+  if (m_used + n > m_data->m_size ||
+      (m_head != 0xffff &&
+       m_data->m_count != 1 &&
+       m_used != m_data->m_dirtyEnd))
+    {
+      ReserveCopy (n);
     }
 
-  uint32_t n = GetUleb128Size (typeUid);
-  n += GetUleb128Size (item->size);
-  n += 2;
-  n += GetUleb128Size (extraItem->fragmentStart);
-  n += GetUleb128Size (extraItem->fragmentEnd);
-  n += 4;
-  n += 2 + 2;
-  ReserveCopy (n);
-  goto append;
+  uint8_t *buffer = &m_data->m_data[m_used];
+
+  Append16 (next, buffer);
+  buffer += 2;
+  Append16 (prev, buffer);
+  buffer += 2;
+  AppendValue (typeUid, buffer);
+  buffer += typeUidSize;
+  AppendValue (item->size, buffer);
+  buffer += sizeSize;
+  Append16 (item->chunkUid, buffer);
+  buffer += 2;
+  AppendValue (extraItem->fragmentStart, buffer);
+  buffer += fragStartSize;
+  AppendValue (extraItem->fragmentEnd, buffer);
+  buffer += fragEndSize;
+  Append32 (extraItem->packetUid, buffer);
+
+  return n;
 }
 
+/**
+ * \param item the item data to write
+ * \param extraItem the extra item data to write
+ * \param available the number of bytes which can 
+ *        be written without having to rewrite the buffer entirely.
+ */
 void
 PacketMetadata::ReplaceTail (PacketMetadata::SmallItem *item, 
                             PacketMetadata::ExtraItem *extraItem,
                             uint32_t available)
 {
+  NS_LOG_FUNCTION (this <<
+                   item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
+                   extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid <<
+                   available);
+
   NS_ASSERT (m_data != 0);  
-  if (available >= 14 &&
+  /* If the tail we want to replace is located at the end of the data array,
+   * and if there is extra room at the end of this array, then, 
+   * we can try to use that extra space to avoid falling in the slow
+   * path below.
+   */
+  if (m_tail + available == m_used &&
+      m_used == m_data->m_dirtyEnd)
+    {
+      available = m_data->m_size - m_tail;
+    }
+
+  uint32_t typeUid = ((item->typeUid & 0x1) == 0x1)?item->typeUid:item->typeUid+1;
+  uint32_t typeUidSize = GetUleb128Size (typeUid);
+  uint32_t sizeSize = GetUleb128Size (item->size);
+  uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
+  uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
+  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
+
+  if (available >= n &&
       m_data->m_count == 1)
     {
       uint8_t *buffer = &m_data->m_data[m_tail];
-      uint8_t *end = buffer + available;
-
       Append16 (item->next, buffer);
       buffer += 2;
       Append16 (item->prev, buffer);
       buffer += 2;
-      if (TryToAppend (item->typeUid, &buffer, end) &&
-          TryToAppend (item->size, &buffer, end) &&
-          TryToAppend16 (item->chunkUid, &buffer, end) &&
-          TryToAppend (extraItem->fragmentStart, &buffer, end) &&
-          TryToAppend (extraItem->fragmentEnd, &buffer, end) &&
-          TryToAppend32 (extraItem->packetUid, &buffer, end))
-        {
-          m_used = buffer - &m_data->m_data[0];
-          m_data->m_dirtyEnd = m_used;
-          return;
-        }
+      AppendValue (typeUid, buffer);
+      buffer += typeUidSize;
+      AppendValue (item->size, buffer);
+      buffer += sizeSize;
+      Append16 (item->chunkUid, buffer);
+      buffer += 2;
+      AppendValue (extraItem->fragmentStart, buffer);
+      buffer += fragStartSize;
+      AppendValue (extraItem->fragmentEnd, buffer);
+      buffer += fragEndSize;
+      Append32 (extraItem->packetUid, buffer);
+      m_used = buffer - &m_data->m_data[0];
+      m_data->m_dirtyEnd = m_used;
+      return;
     }
+
+  /* Below is the slow path which is hit if the new tail we want 
+   * to append is bigger than the previous tail.
+   */
   
   // create a copy of the packet.
   PacketMetadata h (m_packetUid, 0);
@@ -510,6 +455,7 @@
       uint16_t written = h.AddBig (0xffff, h.m_tail, 
                                    &tmpItem, &tmpExtraItem);
       h.UpdateTail (written);
+      current = tmpItem.next;
     }
   // append new tail.
   uint16_t written = h.AddBig (0xffff, h.m_tail, item, extraItem);
@@ -518,11 +464,18 @@
   *this = h;
 }
 
+/**
+ * \param current the offset we should start reading the data from
+ * \param item pointer to where we should store the data to return to the caller
+ * \param extraItem pointer to where we should store the data to return to the caller
+ * \returns the number of bytes read.
+ */
 uint32_t
 PacketMetadata::ReadItems (uint16_t current, 
                           struct PacketMetadata::SmallItem *item,
                           struct PacketMetadata::ExtraItem *extraItem) const
 {
+  NS_LOG_FUNCTION (this << current);
   const uint8_t *buffer = &m_data->m_data[current];
   item->next = buffer[0];
   item->next |= (buffer[1]) << 8;
@@ -644,12 +597,12 @@
 void
 PacketMetadata::DoAddHeader (uint32_t uid, uint32_t size)
 {
+  NS_LOG_FUNCTION (this << uid << size);
   if (!m_enable)
     {
       m_metadataSkipped = true;
       return;
     }
-  NS_LOG_FUNCTION ("uid=" << uid << "size=" << size << "");
 
   struct PacketMetadata::SmallItem item;
   item.next = m_head;
@@ -665,12 +618,12 @@
 PacketMetadata::RemoveHeader (const Header &header, uint32_t size)
 {
   uint32_t uid = header.GetInstanceTypeId ().GetUid () << 1;
+  NS_LOG_FUNCTION (this << uid << size);
   if (!m_enable) 
     {
       m_metadataSkipped = true;
       return;
     }
-  NS_LOG_FUNCTION ("(uid=" << uid << ", size=" << size << ")");
   struct PacketMetadata::SmallItem item;
   struct PacketMetadata::ExtraItem extraItem;
   uint32_t read = ReadItems (m_head, &item, &extraItem);
@@ -703,12 +656,12 @@
 PacketMetadata::AddTrailer (const Trailer &trailer, uint32_t size)
 {
   uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
+  NS_LOG_FUNCTION (this << uid << size);
   if (!m_enable)
     {
       m_metadataSkipped = true;
       return;
     }
-  NS_LOG_FUNCTION ("(uid=" << uid << ", size=" << size << ")");
   struct PacketMetadata::SmallItem item;
   item.next = 0xffff;
   item.prev = m_tail;
@@ -723,12 +676,12 @@
 PacketMetadata::RemoveTrailer (const Trailer &trailer, uint32_t size)
 {
   uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
+  NS_LOG_FUNCTION (this << uid << size);
   if (!m_enable) 
     {
       m_metadataSkipped = true;
       return;
     }
-  NS_LOG_FUNCTION ("(uid=" << uid << ", size=" << size << ")");
   struct PacketMetadata::SmallItem item;
   struct PacketMetadata::ExtraItem extraItem;
   uint32_t read = ReadItems (m_tail, &item, &extraItem);
@@ -760,6 +713,7 @@
 void
 PacketMetadata::AddAtEnd (PacketMetadata const&o)
 {
+  NS_LOG_FUNCTION (this << &o);
   if (!m_enable) 
     {
       m_metadataSkipped = true;
@@ -767,46 +721,52 @@
     }
   if (m_tail == 0xffff)
     {
+      // We have no items so 'AddAtEnd' is 
+      // equivalent to self-assignment.
       *this = o;
       return;
     }
   NS_ASSERT (m_head != 0xffff && m_tail != 0xffff);
 
-  uint16_t lastTail;
-  lastTail = m_tail;
-  struct PacketMetadata::SmallItem lastItem;
-  PacketMetadata::ExtraItem lastExtraItem;
-  uint32_t lastTailSize = ReadItems (m_tail, &lastItem, &lastExtraItem);
-  if (m_tail + lastTailSize == m_used &&
-      m_used == m_data->m_dirtyEnd)
+  // We read the current tail because we are going to append
+  // after this item.
+  struct PacketMetadata::SmallItem tailItem;
+  PacketMetadata::ExtraItem tailExtraItem;
+  uint32_t tailSize = ReadItems (m_tail, &tailItem, &tailExtraItem);
+
+  uint16_t current;
+  struct PacketMetadata::SmallItem item;
+  PacketMetadata::ExtraItem extraItem;
+  o.ReadItems (o.m_head, &item, &extraItem);
+  if (extraItem.packetUid == tailExtraItem.packetUid &&
+      item.typeUid == tailItem.typeUid &&
+      item.chunkUid == tailItem.chunkUid &&
+      item.size == tailItem.size &&
+      extraItem.fragmentStart == tailExtraItem.fragmentEnd)
     {
-      lastTailSize = m_data->m_size - m_tail;
+      /* If the previous tail came from the same header as
+       * the next item we want to append to our array, then, 
+       * we merge them and attempt to reuse the previous tail's
+       * location.
+       */
+      tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
+      ReplaceTail (&tailItem, &tailExtraItem, tailSize);
+      current = item.next;
+    }
+  else
+    {
+      current = o.m_head;
     }
 
-  uint16_t current = o.m_head;
+  /* Now that we have merged our current tail with the head of the
+   * next packet, we just append all items from the next packet
+   * to the current packet.
+   */
   while (current != 0xffff)
     {
-      struct PacketMetadata::SmallItem item;
-      PacketMetadata::ExtraItem extraItem;
       o.ReadItems (current, &item, &extraItem);
-      if (extraItem.packetUid == lastExtraItem.packetUid &&
-          item.typeUid == lastItem.typeUid &&
-          item.chunkUid == lastItem.chunkUid &&
-          item.size == lastItem.size &&
-          extraItem.fragmentStart == lastExtraItem.fragmentEnd)
-        {
-          // replace previous tail.
-          lastExtraItem.fragmentEnd = extraItem.fragmentEnd;
-          NS_ASSERT (m_tail == lastTail);
-          // XXX This call might be wrong. 
-          ReplaceTail (&lastItem, &lastExtraItem, lastTailSize);
-        }
-      else
-        {
-          // append the extra items.
-          uint16_t written = AddBig (0xffff, m_tail, &item, &extraItem);
-          UpdateTail (written);
-        }
+      uint16_t written = AddBig (0xffff, m_tail, &item, &extraItem);
+      UpdateTail (written);
       if (current == o.m_tail)
         {
           break;
@@ -826,6 +786,7 @@
 void 
 PacketMetadata::RemoveAtStart (uint32_t start)
 {
+  NS_LOG_FUNCTION (this << start);
   if (!m_enable) 
     {
       m_metadataSkipped = true;
@@ -891,6 +852,7 @@
 void 
 PacketMetadata::RemoveAtEnd (uint32_t end)
 {
+  NS_LOG_FUNCTION (this << end);
   if (!m_enable) 
     {
       m_metadataSkipped = true;
@@ -1069,6 +1031,7 @@
 uint32_t 
 PacketMetadata::GetSerializedSize (void) const
 {
+  NS_LOG_FUNCTION (this);
   uint32_t totalSize = 0;
   totalSize += 4;
   if (!m_enable)
@@ -1105,6 +1068,7 @@
 void 
 PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
 {
+  NS_LOG_FUNCTION (this);
   uint32_t bytesWritten = 0;
   i.WriteU32 (size);
   bytesWritten += 4;
@@ -1160,6 +1124,7 @@
 uint32_t 
 PacketMetadata::Deserialize (Buffer::Iterator i)
 {
+  NS_LOG_FUNCTION (this);
   struct PacketMetadata::SmallItem item;
   struct PacketMetadata::ExtraItem extraItem;
   uint32_t totalSize = i.ReadU32 ();
--- a/src/common/packet-metadata.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/packet-metadata.h	Wed Jun 04 17:19:32 2008 -0400
@@ -36,6 +36,7 @@
 
 /**
  * \internal
+ * \ingroup packet
  * \brief handle packet metadata about packet headers and trailers
  *
  * This class is used by the Packet class to record every operation
@@ -249,13 +250,11 @@
                     uint32_t available);
   inline void UpdateHead (uint16_t written);
   inline void UpdateTail (uint16_t written);
-  uint32_t GetUleb128Size (uint32_t value) const;
+  inline uint32_t GetUleb128Size (uint32_t value) const;
   uint32_t ReadUleb128 (const uint8_t **pBuffer) const;
   inline void Append16 (uint16_t value, uint8_t *buffer);
-  inline bool TryToAppend (uint32_t value, uint8_t **pBuffer, uint8_t *end);
-  inline bool TryToAppend32 (uint32_t value, uint8_t **pBuffer, uint8_t *end);
-  inline bool TryToAppend16 (uint16_t value, uint8_t **pBuffer, uint8_t *end);
-  void AppendValue (uint32_t value, uint8_t *buffer);
+  inline void Append32 (uint32_t value, uint8_t *buffer);
+  inline void AppendValue (uint32_t value, uint8_t *buffer);
   void AppendValueExtra (uint32_t value, uint8_t *buffer);
   inline void Reserve (uint32_t n);
   void ReserveCopy (uint32_t n);
--- a/src/common/packet.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/packet.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -19,11 +19,63 @@
  */
 #include "packet.h"
 #include "ns3/assert.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("Packet");
 
 namespace ns3 {
 
 uint32_t Packet::m_globalUid = 0;
 
+TypeId 
+TagIterator::Item::GetTypeId (void) const
+{
+  return m_tid;
+}
+uint32_t 
+TagIterator::Item::GetStart (void) const
+{
+  return m_start;
+}
+uint32_t 
+TagIterator::Item::GetEnd (void) const
+{
+  return m_end;
+}
+void 
+TagIterator::Item::GetTag (Tag &tag) const
+{
+  if (tag.GetInstanceTypeId () != GetTypeId ())
+    {
+      NS_FATAL_ERROR ("The tag you provided is not of the right type.");
+    }
+  tag.Deserialize (m_buffer);
+}
+TagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
+  : m_tid (tid),
+    m_start (start),
+    m_end (end),
+    m_buffer (buffer)
+{}
+bool 
+TagIterator::HasNext (void) const
+{
+  return m_current.HasNext ();
+}
+TagIterator::Item 
+TagIterator::Next (void)
+{
+  TagList::Iterator::Item i = m_current.Next ();
+  return TagIterator::Item (i.tid, 
+                            i.start-m_current.GetOffsetStart (), 
+                            i.end-m_current.GetOffsetStart (), 
+                            i.buf);
+}
+TagIterator::TagIterator (TagList::Iterator i)
+  : m_current (i)
+{}
+
+
 void 
 Packet::Ref (void) const
 {
@@ -50,7 +102,7 @@
 
 Packet::Packet ()
   : m_buffer (),
-    m_tags (),
+    m_tagList (),
     m_metadata (m_globalUid, 0),
     m_refCount (1)
 {
@@ -59,7 +111,7 @@
 
 Packet::Packet (const Packet &o)
   : m_buffer (o.m_buffer),
-    m_tags (o.m_tags),
+    m_tagList (o.m_tagList),
     m_metadata (o.m_metadata),
     m_refCount (1)
 {}
@@ -72,14 +124,14 @@
       return *this;
     }
   m_buffer = o.m_buffer;
-  m_tags = o.m_tags;
+  m_tagList = o.m_tagList;
   m_metadata = o.m_metadata;
   return *this;
 }
 
 Packet::Packet (uint32_t size)
   : m_buffer (size),
-    m_tags (),
+    m_tagList (),
     m_metadata (m_globalUid, size),
     m_refCount (1)
 {
@@ -87,7 +139,7 @@
 }
 Packet::Packet (uint8_t const*buffer, uint32_t size)
   : m_buffer (),
-    m_tags (),
+    m_tagList (),
     m_metadata (m_globalUid, size),
     m_refCount (1)
 {
@@ -97,9 +149,9 @@
   i.Write (buffer, size);
 }
 
-Packet::Packet (Buffer buffer, Tags tags, PacketMetadata metadata)
+Packet::Packet (const Buffer &buffer,  const TagList &tagList, const PacketMetadata &metadata)
   : m_buffer (buffer),
-    m_tags (tags),
+    m_tagList (tagList),
     m_metadata (metadata),
     m_refCount (1)
 {}
@@ -107,13 +159,14 @@
 Ptr<Packet>
 Packet::CreateFragment (uint32_t start, uint32_t length) const
 {
+  NS_LOG_FUNCTION (this << start << length);
   Buffer buffer = m_buffer.CreateFragment (start, length);
   NS_ASSERT (m_buffer.GetSize () >= start + length);
   uint32_t end = m_buffer.GetSize () - (start + length);
   PacketMetadata metadata = m_metadata.CreateFragment (start, end);
   // again, call the constructor directly rather than
   // through Create because it is private.
-  return Ptr<Packet> (new Packet (buffer, m_tags, metadata), false);
+  return Ptr<Packet> (new Packet (buffer, m_tagList, metadata), false);
 }
 
 uint32_t 
@@ -125,14 +178,22 @@
 void
 Packet::AddHeader (const Header &header)
 {
+  NS_LOG_FUNCTION (this << &header);
   uint32_t size = header.GetSerializedSize ();
-  m_buffer.AddAtStart (size);
+  uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
+  bool resized = m_buffer.AddAtStart (size);
+  if (resized)
+    {
+      m_tagList.AddAtStart (m_buffer.GetCurrentStartOffset () - orgStart,
+                            m_buffer.GetCurrentStartOffset () + size);
+    }
   header.Serialize (m_buffer.Begin ());
   m_metadata.AddHeader (header, size);
 }
 uint32_t
 Packet::RemoveHeader (Header &header)
 {
+  NS_LOG_FUNCTION (this << &header);
   uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
   m_buffer.RemoveAtStart (deserialized);
   m_metadata.RemoveHeader (header, deserialized);
@@ -141,8 +202,15 @@
 void
 Packet::AddTrailer (const Trailer &trailer)
 {
+  NS_LOG_FUNCTION (this << &trailer);
   uint32_t size = trailer.GetSerializedSize ();
-  m_buffer.AddAtEnd (size);
+  uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
+  bool resized = m_buffer.AddAtEnd (size);
+  if (resized)
+    {
+      m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+                          m_buffer.GetCurrentEndOffset () - size);
+    }
   Buffer::Iterator end = m_buffer.End ();
   trailer.Serialize (end);
   m_metadata.AddTrailer (trailer, size);
@@ -150,6 +218,7 @@
 uint32_t
 Packet::RemoveTrailer (Trailer &trailer)
 {
+  NS_LOG_FUNCTION (this << &trailer);
   uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
   m_buffer.RemoveAtEnd (deserialized);
   m_metadata.RemoveTrailer (trailer, deserialized);
@@ -159,28 +228,43 @@
 void 
 Packet::AddAtEnd (Ptr<const Packet> packet)
 {
+  NS_LOG_FUNCTION (this << packet);
+  uint32_t aStart = m_buffer.GetCurrentStartOffset ();
+  uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
   m_buffer.AddAtEnd (packet->m_buffer);
-  /**
-   * XXX: we might need to merge the tag list of the
-   * other packet into the current packet.
-   */
+  uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
+  m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart, 
+                      appendPrependOffset);
+  TagList copy = packet->m_tagList;
+  copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
+                   appendPrependOffset);
+  m_tagList.Add (copy);
   m_metadata.AddAtEnd (packet->m_metadata);
 }
 void
 Packet::AddPaddingAtEnd (uint32_t size)
 {
-  m_buffer.AddAtEnd (size);
+  NS_LOG_FUNCTION (this << size);
+  uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
+  bool resized = m_buffer.AddAtEnd (size);
+  if (resized)
+    {
+      m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+                          m_buffer.GetCurrentEndOffset () - size);
+    }
   m_metadata.AddPaddingAtEnd (size);
 }
 void 
 Packet::RemoveAtEnd (uint32_t size)
 {
+  NS_LOG_FUNCTION (this << size);
   m_buffer.RemoveAtEnd (size);
   m_metadata.RemoveAtEnd (size);
 }
 void 
 Packet::RemoveAtStart (uint32_t size)
 {
+  NS_LOG_FUNCTION (this << size);
   m_buffer.RemoveAtStart (size);
   m_metadata.RemoveAtStart (size);
 }
@@ -188,7 +272,8 @@
 void 
 Packet::RemoveAllTags (void)
 {
-  m_tags.RemoveAll ();
+  NS_LOG_FUNCTION (this);
+  m_tagList.RemoveAll ();
 }
 
 uint8_t const *
@@ -206,7 +291,30 @@
 void 
 Packet::PrintTags (std::ostream &os) const
 {
-  m_tags.Print (os, " ");
+  TagIterator i = GetTagIterator ();
+  while (i.HasNext ())
+    {
+      TagIterator::Item item = i.Next ();
+      os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
+      Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
+      if (constructor.IsNull ())
+        {
+          if (i.HasNext ())
+            {
+              os << " ";
+            }
+          continue;
+        }
+      Tag *tag = dynamic_cast<Tag *> (constructor ());
+      NS_ASSERT (tag != 0);
+      os << " ";
+      tag->Print (os);
+      if (i.HasNext ())
+        {
+          os << " ";
+        }
+      delete tag;
+    }
 }
 
 void 
@@ -335,12 +443,14 @@
 void
 Packet::EnableMetadata (void)
 {
+  NS_LOG_FUNCTION_NOARGS ();
   PacketMetadata::Enable ();
 }
 
 Buffer 
 Packet::Serialize (void) const
 {
+  NS_LOG_FUNCTION (this);
   Buffer buffer;
   uint32_t reserve;
 
@@ -350,24 +460,25 @@
   m_metadata.Serialize (buffer.Begin (), reserve);
 
   // write tags
-  reserve = m_tags.GetSerializedSize ();
-  buffer.AddAtStart (reserve);
-  m_tags.Serialize (buffer.Begin (), reserve);
+  //XXX
+  //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 ());
+  tmp.AddAtEnd (buffer);
   
   // write byte buffer size.
-  buffer.AddAtStart (4);
-  buffer.Begin ().WriteU32 (m_buffer.GetSize ());
+  tmp.AddAtStart (4);
+  tmp.Begin ().WriteU32 (m_buffer.GetSize ());
 
-  return buffer;
+  return tmp;
 }
 void 
 Packet::Deserialize (Buffer buffer)
 {
+  NS_LOG_FUNCTION (this);
   Buffer buf = buffer;
   // read size
   uint32_t packetSize = buf.Begin ().ReadU32 ();
@@ -376,11 +487,13 @@
   // read buffer.
   buf.RemoveAtEnd (buf.GetSize () - packetSize);
   m_buffer = buf;
+  buffer.RemoveAtStart (4 + packetSize);
+
 
   // read tags
-  buffer.RemoveAtStart (4 + packetSize);
-  uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
-  buffer.RemoveAtStart (tagsDeserialized);
+  //XXX
+  //uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
+  //buffer.RemoveAtStart (tagsDeserialized);
 
   // read metadata
   uint32_t metadataDeserialized = 
@@ -388,6 +501,39 @@
   buffer.RemoveAtStart (metadataDeserialized);
 }
 
+void 
+Packet::AddTag (const Tag &tag) const
+{
+  NS_LOG_FUNCTION (this << &tag);
+  TagList *list = const_cast<TagList *> (&m_tagList);
+  TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (), 
+                                 m_buffer.GetCurrentStartOffset (),
+                                 m_buffer.GetCurrentEndOffset ());
+  tag.Serialize (buffer);
+}
+TagIterator 
+Packet::GetTagIterator (void) const
+{
+  return TagIterator (m_tagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
+}
+
+bool 
+Packet::FindFirstMatchingTag (Tag &tag) const
+{
+  TypeId tid = tag.GetInstanceTypeId ();
+  TagIterator i = GetTagIterator ();
+  while (i.HasNext ())
+    {
+      TagIterator::Item item = i.Next ();
+      if (tid == item.GetTypeId ())
+        {
+          item.GetTag (tag);
+          return true;
+        }
+    }
+  return false;
+}
+
 std::ostream& operator<< (std::ostream& os, const Packet &packet)
 {
   packet.Print (os);
@@ -403,24 +549,190 @@
 
 #include "ns3/test.h"
 #include <string>
+#include <stdarg.h>
+
+using namespace ns3;
+
+namespace {
+
+class ATestTagBase : public Tag
+{
+public:
+  ATestTagBase () : m_error (false) {}
+  bool m_error;
+};
+
+template <int N>
+class ATestTag : public ATestTagBase
+{
+public:
+  static TypeId GetTypeId (void) {
+    std::ostringstream oss;
+    oss << "anon::ATestTag<" << N << ">";
+    static TypeId tid = TypeId (oss.str ().c_str ())
+      .SetParent<Tag> ()
+      .AddConstructor<ATestTag<N> > ()
+      .HideFromDocumentation ()
+      ;
+    return tid;
+  }
+  virtual TypeId GetInstanceTypeId (void) const {
+    return GetTypeId ();
+  }
+  virtual uint32_t GetSerializedSize (void) const {
+    return N;
+  }
+  virtual void Serialize (TagBuffer buf) const {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        buf.WriteU8 (N);
+      }
+  }
+  virtual void Deserialize (TagBuffer buf) {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        uint8_t v = buf.ReadU8 ();
+        if (v != N)
+          {
+            m_error = true;
+          }
+      }
+  }
+  virtual void Print (std::ostream &os) const {
+    os << N;
+  }
+  ATestTag ()
+    : ATestTagBase () {}
+};
+
+class ATestHeaderBase : public Header
+{
+public:
+  ATestHeaderBase () : Header (), m_error (false) {}
+  bool m_error;
+};
+
+template <int N>
+class ATestHeader : public ATestHeaderBase
+{
+public:
+  static TypeId GetTypeId (void) {
+    std::ostringstream oss;
+    oss << "anon::ATestHeader<" << N << ">";
+    static TypeId tid = TypeId (oss.str ().c_str ())
+      .SetParent<Header> ()
+      .AddConstructor<ATestHeader<N> > ()
+      .HideFromDocumentation ()
+      ;
+    return tid;
+  }
+  virtual TypeId GetInstanceTypeId (void) const {
+    return GetTypeId ();
+  }
+  virtual uint32_t GetSerializedSize (void) const {
+    return N;
+  }
+  virtual void Serialize (Buffer::Iterator iter) const {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        iter.WriteU8 (N);
+      }
+  }
+  virtual uint32_t Deserialize (Buffer::Iterator iter) {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        uint8_t v = iter.ReadU8 ();
+        if (v != N)
+          {
+            m_error = true;
+          }
+      }
+    return N;
+  }
+  virtual void Print (std::ostream &os) const {
+  }
+  ATestHeader ()
+    : ATestHeaderBase () {}
+
+};
+
+struct Expected
+{
+  Expected (uint32_t n_, uint32_t start_, uint32_t end_)
+    : n (n_), start (start_), end (end_) {}
+  
+  uint32_t n;
+  uint32_t start;
+  uint32_t end;
+};
+
+}
+
+#define E(a,b,c) a,b,c
+
+#define CHECK(p, n, ...)                                \
+  if (!DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)) \
+    {                                                   \
+      result = false;                                   \
+    }
 
 namespace ns3 {
 
-class PacketTest: public Test {
+
+class PacketTest: public Test 
+{
 public:
+  PacketTest ();
   virtual bool RunTests (void);
-  PacketTest ();
+private:
+  bool DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
 };
 
 
 PacketTest::PacketTest ()
   : Test ("Packet") {}
 
+bool
+PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
+{
+  bool result = true;
+  std::vector<struct Expected> expected;
+  va_list ap;
+  va_start (ap, n);
+  for (uint32_t k = 0; k < n; ++k)
+    {
+      uint32_t N = va_arg (ap, uint32_t);
+      uint32_t start = va_arg (ap, uint32_t);
+      uint32_t end = va_arg (ap, uint32_t);
+      expected.push_back (Expected (N, start, end));
+    }
+  va_end (ap);
+
+  TagIterator i = p->GetTagIterator ();
+  uint32_t j = 0;
+  while (i.HasNext () && j < expected.size ())
+    {
+      TagIterator::Item item = i.Next ();
+      struct Expected e = expected[j];
+      std::ostringstream oss;
+      oss << "anon::ATestTag<" << e.n << ">";
+      NS_TEST_ASSERT_EQUAL_FILELINE (item.GetTypeId ().GetName (), oss.str (), file, line);
+      NS_TEST_ASSERT_EQUAL_FILELINE (item.GetStart (), e.start, file, line);
+      NS_TEST_ASSERT_EQUAL_FILELINE (item.GetEnd (), e.end, file, line);
+      ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
+      NS_TEST_ASSERT (tag != 0);
+      item.GetTag (*tag);
+      NS_TEST_ASSERT (!tag->m_error);
+      delete tag;
+      j++;
+    }
+  return result;
+}
 
 bool
 PacketTest::RunTests (void)
 {
-  bool ok = true;
+  bool result = true;
 
   Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
   Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
@@ -428,25 +740,80 @@
   packet->AddAtEnd (pkt1);
   packet->AddAtEnd (pkt2);
   
-  if (packet->GetSize () != 11)
-    {
-      Failure () << "expected size 11, got " << packet->GetSize () << std::endl;
-      ok = false;
-    }
+  NS_TEST_ASSERT_EQUAL (packet->GetSize (), 11);
 
   std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
                                  packet->GetSize ());
-  if (msg != "hello world")
-    {
-      Failure () << "expected 'hello world', got '" << msg << "'" << std::endl;
-      ok = false;
-    }
+  NS_TEST_ASSERT_EQUAL (msg, "hello world");
+
+
+  Ptr<const Packet> p = Create<Packet> (1000);
+
+  p->AddTag (ATestTag<1> ());
+  CHECK (p, 1, E (1, 0, 1000));
+  Ptr<const Packet> copy = p->Copy ();
+  CHECK (copy, 1, E (1, 0, 1000));
+
+  p->AddTag (ATestTag<2> ());
+  CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
+  CHECK (copy, 1, E (1, 0, 1000));
+
+  {
+    Packet c0 = *copy;
+    Packet c1 = *copy;
+    c0 = c1;
+    CHECK (&c0, 1, E (1, 0, 1000));
+    CHECK (&c1, 1, E (1, 0, 1000));
+    CHECK (copy, 1, E (1, 0, 1000));
+    c0.AddTag (ATestTag<10> ());
+    CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
+    CHECK (&c1, 1, E (1, 0, 1000));
+    CHECK (copy, 1, E (1, 0, 1000));
+  }
 
-  return ok;
+  Ptr<Packet> frag0 = p->CreateFragment (0, 10);
+  Ptr<Packet> frag1 = p->CreateFragment (10, 90);
+  Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
+  frag0->AddTag (ATestTag<3> ());
+  CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
+  frag1->AddTag (ATestTag<4> ());
+  CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
+  frag2->AddTag (ATestTag<5> ());
+  CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
+
+  frag1->AddAtEnd (frag2);
+  CHECK (frag1, 6, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90), E (1, 90, 990), E(2, 90, 990), E (5, 90, 990));
+
+  CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
+  frag0->AddAtEnd (frag1);
+  CHECK (frag0, 9, 
+         E (1, 0, 10), E(2, 0, 10), E (3, 0, 10),
+         E (1, 10, 100), E(2, 10, 100), E (4, 10, 100), 
+         E (1, 100, 1000), E(2, 100, 1000), E (5, 100, 1000));
+
+
+  // force caching a buffer of the right size.
+  frag0 = Create<Packet> (1000);
+  frag0->AddHeader (ATestHeader<10> ());
+  frag0 = 0;
+
+  p = Create<Packet> (1000);
+  p->AddTag (ATestTag<20> ());
+  CHECK (p, 1, E (20, 0, 1000));
+  frag0 = p->CreateFragment (10, 90);
+  CHECK (p, 1, E (20, 0, 1000));
+  CHECK (frag0, 1, E (20, 0, 90));
+  p = 0;
+  frag0->AddHeader (ATestHeader<10> ());
+  CHECK (frag0, 1, E (20, 10, 100));
+
+  
+
+  return result;
 }
 
 
-static PacketTest gPacketTest;
+static PacketTest g_packetTest;
 
 }; // namespace ns3
 
--- a/src/common/packet.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/packet.h	Wed Jun 04 17:19:32 2008 -0400
@@ -24,9 +24,9 @@
 #include "buffer.h"
 #include "header.h"
 #include "trailer.h"
-#include "tags.h"
 #include "packet-metadata.h"
 #include "tag.h"
+#include "tag-list.h"
 #include "ns3/callback.h"
 #include "ns3/assert.h"
 #include "ns3/ptr.h"
@@ -34,9 +34,78 @@
 namespace ns3 {
 
 /**
+ * \ingroup common
+ * \defgroup packet Packet
+ */
+
+/**
+ * \ingroup packet
+ * \brief Iterator over the set of tags in a packet
+ *
+ * This is a java-style iterator.
+ */
+class TagIterator
+{
+public:
+  /**
+   * Identifies a tag and a set of bytes within a packet
+   * to which the tag applies.
+   */
+  class Item
+  {
+  public:
+    /**
+     * \returns the ns3::TypeId associated to this tag.
+     */
+    TypeId GetTypeId (void) const;
+    /**
+     * \returns the index of the first byte tagged by this tag.
+     *
+     * The index is an offset from the start of the packet.
+     */
+    uint32_t GetStart (void) const;
+    /**
+     * \returns the index of the last byte tagged by this tag.
+     *
+     * The index is an offset from the start of the packet.
+     */
+    uint32_t GetEnd (void) const;
+    /**
+     * \param tag the user tag to which the data should be copied.
+     *
+     * Read the requested tag and store it in the user-provided
+     * tag instance. This method will crash if the type of the
+     * tag provided by the user does not match the type of
+     * the underlying tag.
+     */
+    void GetTag (Tag &tag) const;
+  private:
+    friend class TagIterator;
+    Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer);
+    TypeId m_tid;
+    uint32_t m_start;
+    uint32_t m_end;
+    TagBuffer m_buffer;
+  };
+  /**
+   * \returns true if calling Next is safe, false otherwise.
+   */
+  bool HasNext (void) const;
+  /**
+   * \returns the next item found and prepare for the next one.
+   */
+  Item Next (void);
+private:
+  friend class Packet;
+  TagIterator (TagList::Iterator i);
+  TagList::Iterator m_current;
+};
+
+/**
+ * \ingroup packet
  * \brief network packets
  *
- * Each network packet contains a byte buffer, a list of tags, and
+ * Each network packet contains a byte buffer, a set of tags, and
  * metadata.
  *
  * - The byte buffer stores the serialized content of the headers and trailers 
@@ -45,13 +114,10 @@
  * 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. 
- * These tags typically contain per-packet cross-layer information or 
- * flow identifiers. Each tag stored in the tag list can be at most
- * 16 bytes big. Trying to attach bigger data structures will trigger
- * crashes at runtime.
+ * - Each tag tags a subset of the bytes in the packet byte buffer with the 
+ * information stored in the tag. A classic example of a tag is a FlowIdTag 
+ * which contains a flow id: the set of bytes tagged by this tag implicitely 
+ * belong to the attached flow id.
  *
  * - The metadata describes the type of the headers and trailers which
  * were serialized in the byte buffer. The maintenance of metadata is
@@ -83,6 +149,8 @@
    * by getUid).
    */
   Packet ();
+  Packet (const Packet &o);
+  Packet &operator = (const Packet &o);  
   /**
    * Create a packet with a zero-filled payload.
    * The memory necessary for the payload is not allocated:
@@ -152,63 +220,6 @@
    */
   uint32_t RemoveTrailer (Trailer &trailer);
   /**
-   * \param tag a pointer to the tag to attach to this packet.
-   *
-   * 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. The copy constructor of the
-   * tag is invoked to copy it into the tag buffer.
-   *
-   * Note that adding a tag is a const operation which is pretty 
-   * un-intuitive. The rationale is that the content and behavior of
-   * a packet is _not_ changed when a tag is added to a packet: any
-   * code which was not aware of the new tag is going to work just
-   * the same if the new tag is added. The real reason why adding a
-   * tag was made a const operation is to allow a trace sink which gets
-   * a packet to tag the packet, even if the packet is const (and most
-   * trace sources should use const packets because it would be
-   * totally evil to allow a trace sink to modify the content of a
-   * packet).
-   *
-   */
-  template <typename T>
-  void AddTag (T const &tag) const;
-  /**
-   * Remove a tag from this packet. The data stored internally
-   * for this tag is copied in the input tag if an instance
-   * of this tag type is present in the internal buffer. If this
-   * tag type is not present, the input tag is not modified. 
-   *
-   * This operation can be potentially slow and might trigger
-   * unexpectedly large memory allocations. It is thus
-   * usually a better idea to create a copy of this packet,
-   * and invoke removeAllTags on the copy to remove all 
-   * tags rather than remove the tags one by one from a packet.
-   *
-   * \param tag a pointer to the tag to remove from this packet
-   * \returns true if an instance of this tag type is stored
-   *          in this packet, false otherwise.
-   */
-  template <typename T>
-  bool RemoveTag (T &tag);
-  /**
-   * 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
-   *          in this packet, false otherwise.
-   */
-  template <typename T>
-  bool PeekTag (T &tag) const;
-  /**
-   * Remove all the tags stored in this packet. This operation is
-   * much much faster than invoking removeTag n times.
-   */
-  void RemoveAllTags (void);
-  /**
    * \param os output stream in which the data should be printed.
    *
    * Iterate over the tags present in this packet, and
@@ -330,12 +341,47 @@
    * a different CPU.
    */
   void Deserialize (Buffer buffer);
+
+  /**
+   * \param tag the new tag to add to this packet
+   *
+   * Tag each byte included in this packet with the
+   * new tag.
+   *
+   * Note that adding a tag is a const operation which is pretty 
+   * un-intuitive. The rationale is that the content and behavior of
+   * a packet is _not_ changed when a tag is added to a packet: any
+   * code which was not aware of the new tag is going to work just
+   * the same if the new tag is added. The real reason why adding a
+   * tag was made a const operation is to allow a trace sink which gets
+   * a packet to tag the packet, even if the packet is const (and most
+   * trace sources should use const packets because it would be
+   * totally evil to allow a trace sink to modify the content of a
+   * packet).
+   */
+  void AddTag (const Tag &tag) const;
+  /**
+   * \returns an iterator over the set of tags included in this packet.
+   */
+  TagIterator GetTagIterator (void) const;
+  /**
+   * \param tag the tag to search in this packet
+   * \returns true if the requested tag type was found, false otherwise.
+   *
+   * If the requested tag type is found, it is copied in the user's 
+   * provided tag instance.
+   */
+  bool FindFirstMatchingTag (Tag &tag) const;
+
+  /**
+   * Remove all the tags stored in this packet.
+   */
+  void RemoveAllTags (void);
+
 private:
-  Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
-  Packet (const Packet &o);
-  Packet &operator = (const Packet &o);
+  Packet (const Buffer &buffer, const TagList &tagList, const PacketMetadata &metadata);
   Buffer m_buffer;
-  Tags m_tags;
+  TagList m_tagList;
   PacketMetadata m_metadata;
   mutable uint32_t m_refCount;
   static uint32_t m_globalUid;
@@ -357,7 +403,6 @@
  * to detect when an operation is "dirty".
  *
  * Dirty operations:
- *   - ns3::Packet::RemoveTag
  *   - ns3::Packet::AddHeader
  *   - ns3::Packet::AddTrailer
  *   - both versions of ns3::Packet::AddAtEnd
@@ -381,42 +426,4 @@
 
 } // namespace ns3
 
-
-/**************************************************
-  Start of implementation of templates defined
-  above
- *************************************************/
-
-namespace ns3 {
-
-template <typename T>
-void Packet::AddTag (T const& tag) const
-{
-  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
-
 #endif /* PACKET_H */
--- a/src/common/pcap-writer.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/pcap-writer.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -46,7 +46,12 @@
 
 PcapWriter::~PcapWriter ()
 {
+  if (m_writer != 0)
+    {
+      m_writer->close ();
+    }
   delete m_writer;
+  m_writer = 0;
 }
 
 void
--- a/src/common/pcap-writer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/pcap-writer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 class Packet;
 
 /**
+ * \ingroup common
+ *
  * \brief Pcap output for Packet logger
  *
  * Log Packets to a file in pcap format which can be
@@ -49,17 +51,35 @@
 
   /**
    * Write a pcap header in the output file which specifies
-   * that the content of the file will Packets with
+   * that the content of the file will be Packets with
    * Ethernet/LLC/SNAP encapsulation. This method should
    * be invoked before ns3::PcapWriter::writePacket and after
    * ns3::PcapWriter::open.
    */
   void WriteEthernetHeader (void);
 
+  /**
+   * Write a pcap header in the output file which specifies
+   * that the content of the file will be IPv4 Packets. This 
+   * method should be invoked before ns3::PcapWriter::WritePacket 
+   * and after ns3::PcapWriter::Open.
+   */
   void WriteIpHeader (void);
 
+  /**
+   * Write a pcap header in the output file which specifies
+   * that the content of the file will be 802.11 Packets. This 
+   * method should be invoked before ns3::PcapWriter::WritePacket 
+   * and after ns3::PcapWriter::Open.
+   */
   void WriteWifiHeader (void);
 
+  /**
+   * Write a pcap header in the output file which specifies
+   * that the content of the file will be ppp Packets. This 
+   * method should be invoked before ns3::PcapWriter::WritePacket 
+   * and after ns3::PcapWriter::Open.
+   */
   void WritePppHeader (void);
 
   /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-buffer.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,193 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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 "tag-buffer.h"
+#include "ns3/assert.h"
+#include <string.h>
+
+namespace ns3 {
+
+#ifndef TAG_BUFFER_USE_INLINE
+
+void 
+TagBuffer::WriteU8 (uint8_t v)
+{
+  NS_ASSERT (m_current + 1 <= m_end);
+  *m_current = v;
+  m_current++;
+}
+
+void 
+TagBuffer::WriteU16 (uint16_t data)
+{
+  WriteU8 ((data >> 0) & 0xff);
+  WriteU8 ((data >> 8) & 0xff);
+}
+void 
+TagBuffer::WriteU32 (uint32_t data)
+{
+  WriteU8 ((data >> 0) & 0xff);
+  WriteU8 ((data >> 8) & 0xff);
+  WriteU8 ((data >> 16) & 0xff);
+  WriteU8 ((data >> 24) & 0xff);
+}
+
+
+uint8_t  
+TagBuffer::ReadU8 (void)
+{
+  NS_ASSERT (m_current + 1 <= m_end);
+  uint8_t v;
+  v = *m_current;
+  m_current++;
+  return v;
+}
+
+uint16_t 
+TagBuffer::ReadU16 (void)
+{
+  uint8_t byte0 = ReadU8 ();
+  uint8_t byte1 = ReadU8 ();
+  uint16_t data = byte1;
+  data <<= 8;
+  data |= byte0;
+  return data;
+}
+uint32_t 
+TagBuffer::ReadU32 (void)
+{
+  uint8_t byte0 = ReadU8 ();
+  uint8_t byte1 = ReadU8 ();
+  uint8_t byte2 = ReadU8 ();
+  uint8_t byte3 = ReadU8 ();
+  uint32_t data = byte3;
+  data <<= 8;
+  data |= byte2;
+  data <<= 8;
+  data |= byte1;
+  data <<= 8;
+  data |= byte0;
+  return data;
+}
+
+#endif /* TAG_BUFFER_USE_INLINE */
+
+
+void 
+TagBuffer::WriteU64 (uint64_t data)
+{
+  WriteU8 ((data >> 0) & 0xff);
+  WriteU8 ((data >> 8) & 0xff);
+  WriteU8 ((data >> 16) & 0xff);
+  WriteU8 ((data >> 24) & 0xff);
+  WriteU8 ((data >> 32) & 0xff);
+  WriteU8 ((data >> 40) & 0xff);
+  WriteU8 ((data >> 48) & 0xff);
+  WriteU8 ((data >> 54) & 0xff);
+}
+void
+TagBuffer::WriteDouble (double v)
+{
+  uint8_t *buf = (uint8_t *)&v;
+  for (uint32_t i = 0; i < sizeof (double); ++i, ++buf)
+    {
+      WriteU8 (*buf);
+    }
+}
+void 
+TagBuffer::Write (const uint8_t *buffer, uint32_t size)
+{
+  for (uint32_t i = 0; i < size; ++i, ++buffer)
+    {
+      WriteU8 (*buffer);
+    }
+}
+uint64_t 
+TagBuffer::ReadU64 (void)
+{
+  uint8_t byte0 = ReadU8 ();
+  uint8_t byte1 = ReadU8 ();
+  uint8_t byte2 = ReadU8 ();
+  uint8_t byte3 = ReadU8 ();
+  uint8_t byte4 = ReadU8 ();
+  uint8_t byte5 = ReadU8 ();
+  uint8_t byte6 = ReadU8 ();
+  uint8_t byte7 = ReadU8 ();
+  uint32_t data = byte7;
+  data <<= 8;
+  data |= byte6;
+  data <<= 8;
+  data |= byte5;
+  data <<= 8;
+  data |= byte4;
+  data <<= 8;
+  data |= byte3;
+  data <<= 8;
+  data |= byte2;
+  data <<= 8;
+  data |= byte1;
+  data <<= 8;
+  data |= byte0;
+
+  return data;
+}
+double
+TagBuffer::ReadDouble (void)
+{
+  double v;
+  uint8_t *buf = (uint8_t *)&v;
+  for (uint32_t i = 0; i < sizeof (double); ++i, ++buf)
+    {
+      *buf = ReadU8 ();
+    }
+  return v;
+}
+void 
+TagBuffer::Read (uint8_t *buffer, uint32_t size)
+{
+  for (uint32_t i = 0; i < size; ++i, ++buffer)
+    {
+      *buffer = ReadU8 ();
+    }
+}
+TagBuffer::TagBuffer (uint8_t *start, uint8_t *end)
+  : m_current (start),
+    m_end (end)
+{}
+
+void 
+TagBuffer::TrimAtEnd (uint32_t trim)
+{
+  NS_ASSERT (m_current <= (m_end - trim));
+  m_end -= trim;
+}
+
+void 
+TagBuffer::CopyFrom (TagBuffer o)
+{
+  NS_ASSERT (o.m_end >= o.m_current);
+  NS_ASSERT (m_end >= m_current);
+  uintptr_t size = o.m_end - o.m_current;
+  NS_ASSERT (size <= (uintptr_t)(m_end - m_current));
+  memcpy (m_current, o.m_current, size);
+  m_current += size;
+}
+
+} // namespace ns3
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-buffer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,219 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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>
+ */
+#ifndef TAG_BUFFER_H
+#define TAG_BUFFER_H
+
+#include <stdint.h>
+
+#define TAG_BUFFER_USE_INLINE 1
+
+#ifdef TAG_BUFFER_USE_INLINE
+#define TAG_BUFFER_INLINE inline
+#else
+#define TAG_BUFFER_INLINE
+#endif
+
+namespace ns3 {
+
+/**
+ * \ingroup packet
+ *
+ * \brief read and write tag data
+ *
+ * This class allows subclasses of the ns3::Tag base class
+ * to serialize and deserialize their data through a stream-like
+ * API. This class keeps track of the "current" point in the
+ * buffer and advances that "current" point everytime data is 
+ * written. The in-memory format of the data written by 
+ * this class is unspecified.
+ *
+ * If the user attempts to write more data in the buffer than 
+ * he allocated with Tag::GetSerializedSize, he will trigger
+ * an NS_ASSERT error.
+ */
+class TagBuffer
+{
+public:
+  TagBuffer (uint8_t *start, uint8_t *end);
+  void TrimAtEnd (uint32_t trim);
+  void CopyFrom (TagBuffer o);
+
+  /**
+   * \param v the value to write
+   *
+   * Write one byte and advance the "current" point by one.
+   */
+  TAG_BUFFER_INLINE void WriteU8 (uint8_t v);
+  /**
+   * \param v the value to write
+   *
+   * Write two bytes and advance the "current" point by two.
+   */
+  TAG_BUFFER_INLINE void WriteU16 (uint16_t v);
+  /**
+   * \param v the value to write
+   *
+   * Write four bytes and advance the "current" point by four.
+   */
+  TAG_BUFFER_INLINE void WriteU32 (uint32_t v);
+  /**
+   * \param v the value to write
+   *
+   * Write eight bytes and advance the "current" point by eight.
+   */
+  void WriteU64 (uint64_t v);
+  /**
+   * \param v the value to write
+   *
+   * Write a double and advance the "current" point by the size of the
+   * data written.
+   */
+  void WriteDouble (double v);
+  /**
+   * \param buffer a pointer to data to write
+   * \param size the size of the data to write
+   *
+   * Write all the input data and advance the "current" point by the size of the
+   * data written.
+   */
+  void Write (const uint8_t *buffer, uint32_t size);
+  /**
+   * \returns the value read
+   *
+   * Read one byte, advance the "current" point by one,
+   * and return the value read.
+   */
+  TAG_BUFFER_INLINE uint8_t  ReadU8 (void);
+  /**
+   * \returns the value read
+   *
+   * Read two bytes, advance the "current" point by two,
+   * and return the value read.
+   */
+  TAG_BUFFER_INLINE uint16_t ReadU16 (void);
+  /**
+   * \returns the value read
+   *
+   * Read four bytes, advance the "current" point by four,
+   * and return the value read.
+   */
+  TAG_BUFFER_INLINE uint32_t ReadU32 (void);
+  /**
+   * \returns the value read
+   *
+   * Read eight bytes, advance the "current" point by eight,
+   * and return the value read.
+   */
+  uint64_t ReadU64 (void);
+  /**
+   * \returns the value read
+   *
+   * Read a double, advance the "current" point by the size
+   * of the data read, and, return the value read.
+   */
+  double ReadDouble (void);
+  /**
+   * \param buffer a pointer to the buffer where data should be
+   * written.
+   * \param size the number of bytes to read.
+   *
+   * Read the number of bytes requested, advance the "current"
+   * point by the number of bytes read, return.
+   */
+  void Read (uint8_t *buffer, uint32_t size);
+private:
+  
+  uint8_t *m_current;
+  uint8_t *m_end;
+};
+
+} // namespace ns3
+
+#ifdef TAG_BUFFER_USE_INLINE
+
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+void 
+TagBuffer::WriteU8 (uint8_t v)
+{
+  NS_ASSERT (m_current + 1 <= m_end);
+  *m_current = v;
+  m_current++;
+}
+
+void 
+TagBuffer::WriteU16 (uint16_t data)
+{
+  WriteU8 ((data >> 0) & 0xff);
+  WriteU8 ((data >> 8) & 0xff);
+}
+void 
+TagBuffer::WriteU32 (uint32_t data)
+{
+  WriteU8 ((data >> 0) & 0xff);
+  WriteU8 ((data >> 8) & 0xff);
+  WriteU8 ((data >> 16) & 0xff);
+  WriteU8 ((data >> 24) & 0xff);
+}
+
+uint8_t  
+TagBuffer::ReadU8 (void)
+{
+  NS_ASSERT (m_current + 1 <= m_end);
+  uint8_t v;
+  v = *m_current;
+  m_current++;
+  return v;
+}
+
+uint16_t 
+TagBuffer::ReadU16 (void)
+{
+  uint8_t byte0 = ReadU8 ();
+  uint8_t byte1 = ReadU8 ();
+  uint16_t data = byte1;
+  data <<= 8;
+  data |= byte0;
+  return data;
+}
+uint32_t 
+TagBuffer::ReadU32 (void)
+{
+  uint8_t byte0 = ReadU8 ();
+  uint8_t byte1 = ReadU8 ();
+  uint8_t byte2 = ReadU8 ();
+  uint8_t byte3 = ReadU8 ();
+  uint32_t data = byte3;
+  data <<= 8;
+  data |= byte2;
+  data <<= 8;
+  data |= byte1;
+  data <<= 8;
+  data |= byte0;
+  return data;
+}
+
+} // namespace ns3
+
+#endif /* TAG_BUFFER_USE_INLINE */
+
+#endif /* TAG_BUFFER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-list.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,392 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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 "tag-list.h"
+#include <vector>
+
+#define USE_FREE_LIST 1
+#define FREE_LIST_SIZE 1000
+
+namespace ns3 {
+
+struct TagListData {
+  uint32_t size;
+  uint32_t count;
+  uint32_t dirty;
+  uint8_t data[4];
+};
+
+#ifdef USE_FREE_LIST
+static class TagListDataFreeList : public std::vector<struct TagListData *>
+{
+public:
+  ~TagListDataFreeList ();
+} g_freeList;
+static uint32_t g_maxSize = 0;
+
+TagListDataFreeList::~TagListDataFreeList ()
+{
+  for (TagListDataFreeList::iterator i = begin ();
+       i != end (); i++)
+    {
+      uint8_t *buffer = (uint8_t *)(*i);
+      delete [] buffer;
+    }
+}
+#endif /* USE_FREE_LIST */
+
+TagList::Iterator::Item::Item (TagBuffer buf_)
+    : buf (buf_)
+{}
+
+bool 
+TagList::Iterator::HasNext (void) const
+{
+  return m_current < m_end;
+}
+struct TagList::Iterator::Item 
+TagList::Iterator::Next (void)
+{
+  NS_ASSERT (HasNext ());
+  struct Item item = Item (TagBuffer (m_current+16, m_end));
+  item.tid.SetUid (m_nextTid);
+  item.size = m_nextSize;
+  item.start = m_nextStart;
+  item.end = m_nextEnd;
+  item.start = std::max (item.start, m_offsetStart);
+  item.end = std::min (item.end, m_offsetEnd);
+  m_current += 4 + 4 + 4 + 4 + item.size;
+  item.buf.TrimAtEnd (m_end - m_current);
+  PrepareForNext ();
+  return item;
+}
+void
+TagList::Iterator::PrepareForNext (void)
+{
+  while (m_current < m_end)
+    {
+      TagBuffer buf = TagBuffer (m_current, m_end);
+      m_nextTid = buf.ReadU32 ();
+      m_nextSize = buf.ReadU32 ();
+      m_nextStart = buf.ReadU32 ();
+      m_nextEnd = buf.ReadU32 ();
+      if (m_nextStart > m_offsetEnd || m_nextEnd < m_offsetStart)
+	{
+	  m_current += 4 + 4 + 4 + 4 + m_nextSize;
+	}
+      else
+	{
+	  break;
+	}
+    }
+}
+TagList::Iterator::Iterator (uint8_t *start, uint8_t *end, uint32_t offsetStart, uint32_t offsetEnd)
+  : m_current (start),
+    m_end (end),
+    m_offsetStart (offsetStart),
+    m_offsetEnd (offsetEnd)
+{
+  PrepareForNext ();
+}
+
+uint32_t 
+TagList::Iterator::GetOffsetStart (void) const
+{
+  return m_offsetStart;
+}
+
+
+TagList::TagList ()
+  : m_used (0),
+    m_data (0)
+{}
+TagList::TagList (const TagList &o)
+  : m_used (o.m_used),
+    m_data (o.m_data)
+{
+  if (m_data != 0)
+    {
+      m_data->count++;
+    }
+}
+TagList &
+TagList::operator = (const TagList &o)
+{
+  if (this == &o)
+    {
+      return *this;
+    }
+
+  Deallocate (m_data);
+  m_data = o.m_data;
+  m_used = o.m_used;
+  if (m_data != 0)
+    {
+      m_data->count++;
+    }
+  return *this;
+}
+TagList::~TagList ()
+{
+  Deallocate (m_data);
+  m_data = 0;
+  m_used = 0;
+}
+
+TagBuffer
+TagList::Add (TypeId tid, uint32_t bufferSize, uint32_t start, uint32_t end)
+{
+  uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
+  NS_ASSERT (m_used <= spaceNeeded);
+  if (m_data == 0)
+    {
+      m_data = Allocate (spaceNeeded);
+      m_used = 0;
+    } 
+  else if (m_data->size < spaceNeeded ||
+	   (m_data->count != 1 && m_data->dirty != m_used))
+    {
+      struct TagListData *newData = Allocate (spaceNeeded);
+      memcpy (&newData->data, &m_data->data, m_used);
+      Deallocate (m_data);
+      m_data = newData;
+    }
+  TagBuffer tag = TagBuffer (&m_data->data[m_used], 
+			     &m_data->data[spaceNeeded]);
+  tag.WriteU32 (tid.GetUid ());
+  tag.WriteU32 (bufferSize);
+  tag.WriteU32 (start);
+  tag.WriteU32 (end);
+  m_used = spaceNeeded;
+  m_data->dirty = m_used;
+  return tag;
+}
+
+void 
+TagList::Add (const TagList &o)
+{
+  TagList::Iterator i = o.Begin (0, 0xffffffff);
+  while (i.HasNext ())
+    {
+      TagList::Iterator::Item item = i.Next ();
+      TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
+      buf.CopyFrom (item.buf);
+    }
+}
+
+void 
+TagList::RemoveAll (void)
+{
+  Deallocate (m_data);
+  m_data = 0;
+  m_used = 0;
+}
+
+TagList::Iterator 
+TagList::Begin (uint32_t offsetStart, uint32_t offsetEnd) const
+{
+  if (m_data == 0)
+    {
+      return Iterator (0, 0, offsetStart, offsetEnd);
+    }
+  else
+    {
+      return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
+    }
+}
+
+bool 
+TagList::IsDirtyAtEnd (uint32_t appendOffset)
+{
+  TagList::Iterator i = Begin (0, 0xffffffff);
+  while (i.HasNext ())
+    {
+      TagList::Iterator::Item item = i.Next ();
+      if (item.end > appendOffset)
+	{
+	  return true;
+	}
+    }
+  return false;
+}
+
+bool 
+TagList::IsDirtyAtStart (uint32_t prependOffset)
+{
+  TagList::Iterator i = Begin (0, 0xffffffff);
+  while (i.HasNext ())
+    {
+      TagList::Iterator::Item item = i.Next ();
+      if (item.start < prependOffset)
+	{
+	  return true;
+	}
+    }
+  return false;
+}
+
+void 
+TagList::AddAtEnd (int32_t adjustment, uint32_t appendOffset)
+{
+  if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
+    {
+      return;
+    }
+  TagList list;
+  TagList::Iterator i = Begin (0, 0xffffffff);
+  while (i.HasNext ())
+    {
+      TagList::Iterator::Item item = i.Next ();
+      item.start += adjustment;
+      item.end += adjustment;
+
+      if (item.start > appendOffset)
+	{
+	  continue;
+	}
+      else if (item.start < appendOffset && item.end > appendOffset)
+	{
+	  item.end = appendOffset;
+	}
+      else
+	{
+	  // nothing to do.
+	}
+      TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+      buf.CopyFrom (item.buf);
+    }
+  *this = list;  
+}
+
+void 
+TagList::AddAtStart (int32_t adjustment, uint32_t prependOffset)
+{
+  if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
+    {
+      return;
+    }
+  TagList list;
+  TagList::Iterator i = Begin (0, 0xffffffff);
+  while (i.HasNext ())
+    {
+      TagList::Iterator::Item item = i.Next ();
+      item.start += adjustment;
+      item.end += adjustment;
+
+      if (item.end < prependOffset)
+	{
+	  continue;
+	}
+      else if (item.end > prependOffset && item.start < prependOffset)
+	{
+	  item.start = prependOffset;
+	}
+      else
+	{
+	  // nothing to do.
+	}
+      TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+      buf.CopyFrom (item.buf);
+    }
+  *this = list;    
+}
+
+#ifdef USE_FREE_LIST
+
+struct TagListData *
+TagList::Allocate (uint32_t size)
+{
+  while (!g_freeList.empty ())
+    {
+      struct TagListData *data = g_freeList.back ();
+      g_freeList.pop_back ();
+      NS_ASSERT (data != 0);
+      if (data->size >= size)
+	{
+	  data->count = 1;
+	  data->dirty = 0;
+	  return data;
+	}
+      uint8_t *buffer = (uint8_t *)data;
+      delete [] buffer;
+    }
+  uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct TagListData) - 4];
+  struct TagListData *data = (struct TagListData *)buffer;
+  data->count = 1;
+  data->size = size;
+  data->dirty = 0;
+  return data;
+}
+
+void 
+TagList::Deallocate (struct TagListData *data)
+{
+  if (data == 0)
+    {
+      return;
+    }
+  g_maxSize = std::max (g_maxSize, data->size);
+  data->count--;
+  if (data->count == 0)
+    {
+      if (g_freeList.size () > FREE_LIST_SIZE ||
+	  data->size < g_maxSize)
+	{
+	  uint8_t *buffer = (uint8_t *)data;
+	  delete [] buffer;
+	}
+      else
+	{
+	  g_freeList.push_back (data);
+	}
+    }
+}
+
+#else /* USE_FREE_LIST */
+
+struct TagListData *
+TagList::Allocate (uint32_t size)
+{
+  uint8_t *buffer = new uint8_t [size + sizeof (struct TagListData) - 4];
+  struct TagListData *data = (struct TagListData *)buffer;
+  data->count = 1;
+  data->size = size;
+  data->dirty = 0;
+  return data;
+}
+
+void 
+TagList::Deallocate (struct TagListData *data)
+{
+  if (data == 0)
+    {
+      return;
+    }
+  data->count--;
+  if (data->count == 0)
+    {
+      uint8_t *buffer = (uint8_t *)data;
+      delete [] buffer;
+    }
+}
+
+#endif /* USE_FREE_LIST */
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/tag-list.h	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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>
+ */
+#ifndef TAG_LIST_H
+#define TAG_LIST_H
+
+#include <stdint.h>
+#include "ns3/type-id.h"
+#include "tag-buffer.h"
+
+namespace ns3 {
+
+struct TagListData;
+
+/**
+ * \ingroup packet
+ *
+ * \brief keep track of the tags stored in a packet.
+ *
+ * This class is mostly private to the Packet implementation and users
+ * should never have to access it directly.
+ *
+ * \internal
+ * The implementation of this class is a bit tricky so, there are a couple
+ * of things to keep in mind here:
+ *
+ *   - it stores all tags in a single byte buffer: each tag is stored
+ *     as 4 32bit integers (TypeId, tag data size, start, end) followed 
+ *     by the tag data as generated by Tag::Serialize.
+ *
+ *   - the struct TagListData structure which contains the tag byte buffer
+ *     is shared and, thus, reference-counted. This data structure is unshared
+ *     as-needed to emulate COW semantics.
+ *
+ *   - each tag tags a unique set of bytes identified by the pair of offsets 
+ *     (start,end). These offsets are provided by Buffer::GetCurrentStartOffset
+ *     and Buffer::GetCurrentEndOffset which means that they are relative to 
+ *     the start of the 'virtual byte buffer' as explained in the documentation
+ *     for the ns3::Buffer class. Whenever the origin of the offset of the Buffer
+ *     instance associated to this TagList instance changes, the Buffer class
+ *     reports this to its container Packet class as a bool return value
+ *     in Buffer::AddAtStart and Buffer::AddAtEnd. In both cases, when this happens
+ *     the Packet class calls TagList::AddAtEnd and TagList::AddAtStart to update
+ *     the byte offsets of each tag in the TagList.
+ *
+ *   - whenever bytes are removed from the packet byte buffer, the TagList offsets 
+ *     are never updated because we rely on the fact that they will be updated in
+ *     either the next call to Packet::AddHeader or Packet::AddTrailer or when
+ *     the user iterates the tag list with Packet::GetTagIterator and 
+ *     TagIterator::Next.
+ */
+class TagList
+{
+public:
+
+  class Iterator
+  {
+  public:
+    struct Item 
+    {
+      TypeId tid;
+      uint32_t size;
+      uint32_t start;
+      uint32_t end;
+      TagBuffer buf;
+      Item (TagBuffer buf);
+    private:
+      friend class TagList;
+      friend class TagList::Iterator;
+    };
+    bool HasNext (void) const;
+    struct TagList::Iterator::Item Next (void);
+    uint32_t GetOffsetStart (void) const;
+  private:
+    friend class TagList;
+    Iterator (uint8_t *start, uint8_t *end, uint32_t offsetStart, uint32_t offsetEnd);
+    void PrepareForNext (void);
+    uint8_t *m_current;
+    uint8_t *m_end;
+    uint32_t m_offsetStart;
+    uint32_t m_offsetEnd;
+    uint32_t m_nextTid;
+    uint32_t m_nextSize;
+    uint32_t m_nextStart;
+    uint32_t m_nextEnd;
+  };
+
+  TagList ();
+  TagList (const TagList &o);
+  TagList &operator = (const TagList &o);
+  ~TagList ();
+
+  /**
+   * \param tid the typeid of the tag added
+   * \param bufferSize the size of the tag when its serialization will 
+   *        be completed. Typically, the return value of Tag::GetSerializedSize
+   * \param start offset which uniquely identifies the first byte tagged by this tag.
+   * \param end offset which uniquely identifies the last byte tagged by this tag.
+   * \returns a buffer which can be used to write the tag data.     
+   *
+   * 
+   */
+  TagBuffer Add (TypeId tid, uint32_t bufferSize, uint32_t start, uint32_t end);
+
+  /**
+   * \param o the other list of tags to aggregate.
+   *
+   * Aggregate the two lists of tags.
+   */
+  void Add (const TagList &o);
+
+  void RemoveAll (void);
+
+  /**
+   * \param offsetStart the offset which uniquely identifies the first data byte 
+   *        present in the byte buffer associated to this TagList.
+   * \param offsetEnd the offset which uniquely identifies the last data byte 
+   *        present in the byte buffer associated to this TagList.
+   * \returns an iterator
+   *
+   * The returned iterator will allow you to loop through the set of tags present
+   * in this list: the boundaries of each tag as reported by their start and
+   * end offsets will be included within the input offsetStart and offsetEnd.
+   */
+  TagList::Iterator Begin (uint32_t offsetStart, uint32_t offsetEnd) const;
+
+  /**
+   * Adjust the offsets stored internally by the adjustment delta and
+   * make sure that all offsets are smaller than appendOffset which represents
+   * the location where new bytes have been added to the byte buffer.
+   */
+  void AddAtEnd (int32_t adjustment, uint32_t appendOffset);
+  /**
+   * Adjust the offsets stored internally by the adjustment delta and
+   * make sure that all offsets are bigger than prependOffset which represents
+   * the location where new bytes have been added to the byte buffer.
+   */
+  void AddAtStart (int32_t adjustment, uint32_t prependOffset);
+
+private:
+  bool IsDirtyAtEnd (uint32_t appendOffset);
+  bool IsDirtyAtStart (uint32_t prependOffset);
+
+  struct TagListData *Allocate (uint32_t size);
+  void Deallocate (struct TagListData *data);
+
+  uint16_t m_used;
+  struct TagListData *m_data;
+};
+
+} // namespace ns3
+
+#endif /* TAG_LIST_H */
--- a/src/common/tag-registry.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 "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
--- a/src/common/tag-registry.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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>
- */
-#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.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,34 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 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 "tag.h"
+
+namespace ns3 {
+
+TypeId 
+Tag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Tag")
+    .SetParent<ObjectBase> ()
+    ;
+  return tid;
+}
+
+
+} // namespace ns3
--- a/src/common/tag.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/tag.h	Wed Jun 04 17:19:32 2008 -0400
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2006 INRIA
+ * Copyright (c) 2008 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
@@ -20,106 +20,56 @@
 #ifndef TAG_H
 #define TAG_H
 
+#include "ns3/object-base.h"
+#include "tag-buffer.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.
+ * \ingroup 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
+ * \brief tag a set of bytes in a packet
  *
- * 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
+ * New kinds of tags can be created by subclassing this base class.
  */
-class Tag
+class Tag : public ObjectBase
 {
-protected:
+public:
+  static TypeId GetTypeId (void);
+
+  /**
+   * \returns the number of bytes required to serialize the data of the tag.
+   *
+   * This method is typically invoked by Packet::AddTag just prior to calling
+   * Tag::Serialize.
+   */
+  virtual uint32_t GetSerializedSize (void) const = 0;
   /**
-   * \param name the unique name of the new type of tag
-   * \returns a newly-allocated uid
+   * \param i the buffer to write data into.
+   *
+   * Write the content of the tag in the provided tag buffer.
+   * DO NOT attempt to write more bytes than you requested
+   * with Tag::GetSerializedSize.
+   */
+  virtual void Serialize (TagBuffer i) const = 0;
+  /**
+   * \param i the buffer to read data from.
    *
-   * This method should be used by subclasses to implement
-   * their static public GetUid method.
+   * Read the content of the tag from the provided tag buffer.
+   * DO NOT attempt to read more bytes than you wrote with
+   * Tag::Serialize.
    */
-  template <typename T>
-  static uint32_t AllocateUid (std::string name);
+  virtual void Deserialize (TagBuffer i) = 0;
+
+  /**
+   * \param os the stream to print to
+   *
+   * This method is typically invoked from the Packet::PrintTags method
+   */
+  virtual void Print (std::ostream &os) const = 0;
 };
 
 } // 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	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,529 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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 "tags.h"
-#include <string.h>
-#include "ns3/fatal-error.h"
-
-namespace ns3 {
-
-#ifdef USE_FREE_LIST
-
-struct Tags::TagData *Tags::gFree = 0;
-uint32_t Tags::gN_free = 0;
-
-struct Tags::TagData *
-Tags::AllocData (void) const
-{
-  struct Tags::TagData *retval;
-  if (gFree != 0) 
-    {
-      retval = gFree;
-      gFree = gFree->m_next;
-      gN_free--;
-    } 
-  else 
-    {
-      retval = new struct Tags::TagData ();
-    }
-  return retval;
-}
-
-void
-Tags::FreeData (struct TagData *data) const
-{
-  if (gN_free > 1000) 
-    {
-      delete data;
-      return;
-    }
-  gN_free++;
-  data->m_next = gFree;
-  data->m_id = 0;
-  gFree = data;
-}
-#else
-struct Tags::TagData *
-Tags::AllocData (void) const
-{
-  struct Tags::TagData *retval;
-  retval = new struct Tags::TagData ();
-  return retval;
-}
-
-void
-Tags::FreeData (struct TagData *data) const
-{
-  delete data;
-}
-#endif
-
-bool
-Tags::Remove (uint32_t id)
-{
-  bool found = false;
-  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
-    {
-      if (cur->m_id == id) 
-        {
-          found = true;
-        }
-    }
-  if (!found) 
-    {
-      return false;
-    }
-  struct TagData *start = 0;
-  struct TagData **prevNext = &start;
-  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
-    {
-      if (cur->m_id == id) 
-        {
-          /**
-           * XXX
-           * Note: I believe that we could optimize this to
-           * avoid copying each TagData located after the target id
-           * and just link the already-copied list to the next tag.
-           */
-          continue;
-        }
-      struct TagData *copy = AllocData ();
-      copy->m_id = cur->m_id;
-      copy->m_count = 1;
-      copy->m_next = 0;
-      memcpy (copy->m_data, cur->m_data, Tags::SIZE);
-      *prevNext = copy;
-      prevNext = &copy->m_next;
-    }
-  *prevNext = 0;
-  RemoveAll ();
-  m_next = start;
-  return true;
-}
-
-void 
-Tags::Print (std::ostream &os, std::string separator) const
-{
-  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
-    {
-      TagRegistry::Print (cur->m_id, cur->m_data, os);
-      if (cur->m_next != 0)
-        {
-          os << 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
-
-#ifdef RUN_SELF_TESTS
-
-#include "ns3/test.h"
-#include <iomanip>
-#include <iostream>
-
-namespace ns3 {
-
-static bool g_a;
-static bool g_b;
-static bool g_c;
-static bool g_z;
-
-class TagsTest : Test {
-public:
-  TagsTest ();
-  virtual ~TagsTest ();
-  virtual bool RunTests (void);
-};
-
-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;
-};
-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;
-};
-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];
-};
-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];
-};
-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 : 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;
-  }
-  MySmartTag (const MySmartTag &o)
-  {
-    //std::cout << "copy" << std::endl;
-  }
-  ~MySmartTag ()
-  {
-    //std::cout << "destruct" << std::endl;
-  }
-  MySmartTag &operator = (const MySmartTag &o)
-  {
-    //std::cout << "assign" << std::endl;
-    return *this;
-  }
-  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;}
-};
-
-
-TagsTest::TagsTest ()
-  : Test ("Tags")
-{}
-TagsTest::~TagsTest ()
-{}
-
-bool 
-TagsTest::RunTests (void)
-{
-  bool ok = true;
-
-  // build initial tag.
-  Tags tags;
-  myTagA a;
-  a.a = 10;
-  tags.Add (a);
-  a.a = 0;
-  tags.Peek (a);
-  if (a.a != 10) 
-    {
-      ok = false;
-    }
-  g_a = false;
-  tags.Print (std::cout, "");
-  if (!g_a)
-    {
-      ok = false;
-    }
-  myTagB b;
-  b.b = 0xff;
-  tags.Add (b);
-  b.b = 0;
-  tags.Peek (b);
-  if (b.b != 0xff) 
-    {
-      ok = false;
-    }
-  g_b = false;
-  g_a = false;
-  tags.Print (std::cout, "");
-  if (!g_a || !g_b)
-    {
-      ok = false;
-    }
-  // make sure copy contains copy.
-  Tags other = tags;
-  g_b = false;
-  g_a = false;
-  other.Print (std::cout, "");
-  if (!g_a || !g_b)
-    {
-      ok = false;
-    }
-  g_b = false;
-  g_a = false;
-  tags.Print (std::cout, "");
-  if (!g_a || !g_b)
-    {
-      ok = false;
-    }
-  myTagA oA;
-  oA.a = 0;
-  other.Peek (oA);
-  if (oA.a != 10) 
-    {
-      ok = false;
-    }
-  myTagB oB;
-  oB.b = 1;
-  other.Peek (oB);
-  if (oB.b != 0xff) 
-    {
-      ok = false;
-    }
-  // remove data.
-  other.Remove (oA);
-  if (other.Peek (oA)) 
-    {
-      ok = false;
-    }
-  g_b = false;
-  g_a = false;
-  other.Print (std::cout, "");
-  if (g_a || !g_b)
-    {
-      ok = false;
-    }
-  if (!tags.Peek (oA)) 
-    {
-      ok = false;
-    }
-  other.Remove (oB);
-  if (other.Peek (oB)) 
-    {
-      ok = false;
-    }
-  if (!tags.Peek (oB)) 
-    {
-      ok = false;
-    }
-
-  other = tags;
-  Tags another = other;
-  myTagC c;
-  memset (c.c, 0x66, 16);
-  another.Add (c);
-  c.c[0] = 0;
-  another.Peek (c);
-  if (!another.Peek (c)) 
-    {
-      ok = false;
-    }
-  if (tags.Peek (c)) 
-    {
-      ok = false;
-    }
-
-  other = other;
-  //other.prettyPrint (std::cout);
-
-  //struct myInvalidTag invalid;
-  //tags.add (&invalid);
-
-  myTagZ tagZ;
-  Tags testLastTag;
-  tagZ.z = 0;
-  testLastTag.Add (tagZ);
-  g_z = false;
-  testLastTag.Print (std::cout, "");
-  if (!g_z)
-    {
-      ok = false;
-    }
-
-  MySmartTag smartTag;
-  {
-    Tags tmp;
-    tmp.Add (smartTag);
-    tmp.Peek (smartTag);
-    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;
-}
-
-static TagsTest gTagsTest;
-
-
-}; // namespace ns3
-
-#endif /* RUN_SELF_TESTS */
-
--- a/src/common/tags.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,228 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2006 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>
- */
-#ifndef TAGS_H
-#define TAGS_H
-
-#include <stdint.h>
-#include <ostream>
-#include <vector>
-#include "buffer.h"
-
-namespace ns3 {
-
-/**
- * \ingroup constants
- * \brief Tag maximum size
- * The maximum size (in bytes) of a Tag is stored
- * in this constant.
- */
-#define TAGS_MAX_SIZE 32
-
-class Tags {
-public:
-  inline Tags ();
-  inline Tags (Tags const &o);
-  inline Tags &operator = (Tags const &o);
-  inline ~Tags ();
-
-  template <typename T>
-  void Add (T const&tag) const;
-
-  template <typename T>
-  bool Remove (T &tag);
-
-  template <typename T>
-  bool Peek (T &tag) const;
-
-  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);
-
-  enum {
-      SIZE = TAGS_MAX_SIZE
-  };
-private:
-  struct TagData {
-      uint8_t m_data[Tags::SIZE];
-      struct TagData *m_next;
-      uint32_t m_id;
-      uint32_t m_count;
-  };
-
-  bool Remove (uint32_t id);
-  struct Tags::TagData *AllocData (void) const;
-  void FreeData (struct TagData *data) const;
-
-  static struct Tags::TagData *gFree;
-  static uint32_t gN_free;
-
-  struct TagData *m_next;
-};
-
-} // namespace ns3
-
-
-
-/**************************************************************
-   An implementation of the templates defined above
- *************************************************************/
-#include "tag-registry.h"
-#include "tag.h"
-#include "ns3/assert.h"
-#include <string>
-
-namespace ns3 {
-
-template <typename T>
-void 
-Tags::Add (T const&tag) const
-{
-  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 != T::GetUid ());
-    }
-  struct TagData *newStart = AllocData ();
-  newStart->m_count = 1;
-  newStart->m_next = 0;
-  newStart->m_id = T::GetUid ();
-  void *buf = &newStart->m_data;
-  new (buf) T (tag);
-  newStart->m_next = m_next;
-  const_cast<Tags *> (this)->m_next = newStart;
-}
-
-template <typename T>
-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);
-  if (Peek (tag))
-    {
-      Remove (T::GetUid ());
-      return true;
-    }
-  else
-    {
-      return false;
-    }
-}
-
-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 == T::GetUid ()) 
-        {
-          /* found tag */
-          T *data = reinterpret_cast<T *> (&cur->m_data);
-          tag = T (*data);
-          return true;
-        }
-    }
-  /* no tag found */
-  return false;
-}
-
-Tags::Tags ()
-  : m_next ()
-{}
-
-Tags::Tags (Tags const &o)
-  : m_next (o.m_next)
-{
-  if (m_next != 0) 
-    {
-      m_next->m_count++;
-    }
-}
-
-Tags &
-Tags::operator = (Tags const &o)
-{
-  // self assignment
-  if (m_next == o.m_next) 
-    {
-      return *this;
-    }
-  RemoveAll ();
-  m_next = o.m_next;
-  if (m_next != 0) 
-    {
-      m_next->m_count++;
-    }
-  return *this;
-}
-
-Tags::~Tags ()
-{
-  RemoveAll ();
-}
-
-void
-Tags::RemoveAll (void)
-{
-  struct TagData *prev = 0;
-  for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next) 
-    {
-      cur->m_count--;
-      if (cur->m_count > 0) 
-        {
-          break;
-        }
-      if (prev != 0) 
-        {
-          TagRegistry::Destruct (prev->m_id, prev->m_data);
-          FreeData (prev);
-        }
-      prev = cur;
-    }
-  if (prev != 0) 
-    {
-      TagRegistry::Destruct (prev->m_id, prev->m_data);
-      FreeData (prev);
-    }
-  m_next = 0;
-}
-
-
-}; // namespace ns3
-
-#endif /* TAGS_H */
--- a/src/common/trailer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/trailer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,13 +29,13 @@
 namespace ns3 {
 
 /**
+ * \ingroup packet
+ *
  * \brief Protocol trailer serialization and deserialization.
  *
  * Every Protocol trailer which needs to be inserted or removed
  * 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.
+ * implement the pure virtual methods defined here.
  */
 class Trailer : public Chunk
 {
--- a/src/common/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/common/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -7,14 +7,15 @@
         'packet-metadata.cc',
         'packet-metadata-test.cc',
         'packet.cc',
-        'tags.cc',
-        'tag-registry.cc',
         'chunk.cc',
         'header.cc',
         'trailer.cc',
         'pcap-writer.cc',
         'data-rate.cc',
         'error-model.cc',
+        'tag.cc',
+        'tag-list.cc',
+        'tag-buffer.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -24,12 +25,12 @@
         'chunk.h',
         'header.h',
         'trailer.h',
-        'tags.h',
-        'tag-registry.h',
-        'tag.h',
         'packet.h',
         'packet-metadata.h',
         'pcap-writer.h',
         'data-rate.h',
         'error-model.h',
+        'tag.h',
+        'tag-list.h',
+        'tag-buffer.h',
         ]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/attribute-iterator.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,274 @@
+#include "attribute-iterator.h"
+#include "ns3/config.h"
+#include "ns3/log.h"
+#include "ns3/pointer.h"
+#include "ns3/object-vector.h"
+#include "ns3/string.h"
+#include <fstream>
+
+
+NS_LOG_COMPONENT_DEFINE ("AttributeIterator");
+
+namespace ns3 {
+
+
+AttributeIterator::AttributeIterator ()
+{}
+
+AttributeIterator::~AttributeIterator ()
+{}
+
+void 
+AttributeIterator::Iterate (void)
+{
+  for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
+    {
+      Ptr<Object> object = Config::GetRootNamespaceObject (i);
+      StartVisitObject (object);
+      DoIterate (object);
+      EndVisitObject ();
+    }
+  NS_ASSERT (m_currentPath.empty ());
+  NS_ASSERT (m_examined.empty ());
+}
+
+bool
+AttributeIterator::IsExamined (Ptr<const Object> object)
+{
+  for (uint32_t i = 0; i < m_examined.size (); ++i)
+    {
+      if (object == m_examined[i])
+	{
+	  return true;
+	}
+    }
+  return false;
+}
+
+
+std::string
+AttributeIterator::GetCurrentPath (std::string attr) const
+{
+  std::ostringstream oss;
+  for (uint32_t i = 0; i < m_currentPath.size (); ++i)
+    {
+      oss << "/" << m_currentPath[i];
+    }
+  if (attr != "")
+    {
+      oss << "/" << attr;
+    }
+  return oss.str ();
+}
+
+std::string
+AttributeIterator::GetCurrentPath (void) const
+{
+  std::ostringstream oss;
+  for (uint32_t i = 0; i < m_currentPath.size (); ++i)
+    {
+      oss << "/" << m_currentPath[i];
+    }
+  return oss.str ();
+}
+
+void 
+AttributeIterator::DoStartVisitObject (Ptr<Object> object)
+{}
+void 
+AttributeIterator::DoEndVisitObject (void)
+{}
+void 
+AttributeIterator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> item)
+{}
+void 
+AttributeIterator::DoEndVisitPointerAttribute (void)
+{}
+void 
+AttributeIterator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
+{}
+void 
+AttributeIterator::DoEndVisitArrayAttribute (void)
+{}
+void 
+AttributeIterator::DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
+{}
+void 
+AttributeIterator::DoEndVisitArrayItem (void)
+{}
+
+void 
+AttributeIterator::VisitAttribute (Ptr<Object> object, std::string name)
+{
+  m_currentPath.push_back (name);
+  DoVisitAttribute (object, name);
+  m_currentPath.pop_back ();
+}
+
+void 
+AttributeIterator::StartVisitObject (Ptr<Object> object)
+{
+  m_currentPath.push_back ("$" + object->GetInstanceTypeId ().GetName ());
+  DoStartVisitObject (object);
+}
+void 
+AttributeIterator::EndVisitObject (void)
+{
+  m_currentPath.pop_back ();
+  DoEndVisitObject ();
+}
+void 
+AttributeIterator::StartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value)
+{
+  m_currentPath.push_back (name);
+  m_currentPath.push_back ("$" + value->GetInstanceTypeId ().GetName ());
+  DoStartVisitPointerAttribute (object, name, value);
+}
+void 
+AttributeIterator::EndVisitPointerAttribute (void)
+{
+  m_currentPath.pop_back ();
+  m_currentPath.pop_back ();
+  DoEndVisitPointerAttribute ();
+}
+void 
+AttributeIterator::StartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
+{
+  m_currentPath.push_back (name);
+  DoStartVisitArrayAttribute (object, name, vector);
+}
+void 
+AttributeIterator::EndVisitArrayAttribute (void)
+{
+  m_currentPath.pop_back ();
+  DoEndVisitArrayAttribute ();
+}
+
+void 
+AttributeIterator::StartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
+{
+  std::ostringstream oss;
+  oss << index;
+  m_currentPath.push_back (oss.str ());
+  m_currentPath.push_back ("$" + item->GetInstanceTypeId ().GetName ());
+  DoStartVisitArrayItem (vector, index, item);
+}
+void 
+AttributeIterator::EndVisitArrayItem (void)
+{
+  m_currentPath.pop_back ();
+  m_currentPath.pop_back ();
+  DoEndVisitArrayItem ();
+}
+
+
+void
+AttributeIterator::DoIterate (Ptr<Object> object)
+{
+  if (IsExamined (object))
+    {
+      return;
+    }
+  TypeId tid;
+  for (tid = object->GetInstanceTypeId (); tid.HasParent (); tid = tid.GetParent ())
+    {
+      NS_LOG_DEBUG ("store " << tid.GetName ());
+      for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
+	{
+	  Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
+	  const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (checker));
+	  if (ptrChecker != 0)
+	    {
+	      NS_LOG_DEBUG ("pointer attribute " << tid.GetAttributeName (i));
+	      PointerValue ptr;
+	      object->GetAttribute (tid.GetAttributeName (i), ptr);
+	      Ptr<Object> tmp = ptr.Get<Object> ();
+	      if (tmp != 0)
+		{
+		  StartVisitPointerAttribute (object, tid.GetAttributeName (i), tmp);
+		  m_examined.push_back (object);
+		  DoIterate (tmp);
+		  m_examined.pop_back ();
+		  EndVisitPointerAttribute ();
+		}
+	      continue;
+	    }
+	  // attempt to cast to an object vector.
+	  const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (checker));
+	  if (vectorChecker != 0)
+	    {
+	      NS_LOG_DEBUG ("vector attribute " << tid.GetAttributeName (i));
+	      ObjectVectorValue vector;
+	      object->GetAttribute (tid.GetAttributeName (i), vector);
+	      StartVisitArrayAttribute (object, tid.GetAttributeName (i), vector);
+	      for (uint32_t j = 0; j < vector.GetN (); ++j)
+		{
+		  NS_LOG_DEBUG ("vector attribute item " << j);
+		  Ptr<Object> tmp = vector.Get (j);
+		  StartVisitArrayItem (vector, j, tmp);
+		  m_examined.push_back (object);
+		  DoIterate (tmp);
+		  m_examined.pop_back ();
+		  EndVisitArrayItem ();
+		}
+	      EndVisitArrayAttribute ();
+	      continue;
+	    }
+	  uint32_t flags = tid.GetAttributeFlags (i);
+	  Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (i);
+	  if ((flags & TypeId::ATTR_GET) && accessor->HasGetter () &&
+	      (flags & TypeId::ATTR_SET) && accessor->HasSetter ())
+	    {
+	      VisitAttribute (object, tid.GetAttributeName (i));
+	    }
+	  else
+	    {
+	      NS_LOG_DEBUG ("could not store " << tid.GetAttributeName (i));
+	    }
+	}
+    }
+  Object::AggregateIterator iter = object->GetAggregateIterator ();
+  bool recursiveAggregate = false;
+  while (iter.HasNext ())
+    {
+      Ptr<const Object> tmp = iter.Next ();
+      if (IsExamined (tmp))
+	{
+	  recursiveAggregate = true;
+	}
+    }
+  if (!recursiveAggregate)
+    {
+      iter = object->GetAggregateIterator ();
+      while (iter.HasNext ())
+	{
+	  Ptr<Object> tmp = const_cast<Object *> (PeekPointer (iter.Next ()));
+	  StartVisitObject (tmp);
+	  m_examined.push_back (object);
+	  DoIterate (tmp);
+	  m_examined.pop_back ();
+	  EndVisitObject ();
+	}
+    }
+}
+
+TextFileAttributeIterator::TextFileAttributeIterator (std::ostream &os)
+  : m_os (os)
+{}
+void 
+TextFileAttributeIterator::DoVisitAttribute (Ptr<Object> object, std::string name)
+{
+  StringValue str;
+  object->GetAttribute (name, str);
+  m_os << GetCurrentPath () << " " << str.Get () << std::endl;
+}
+
+void 
+TextFileAttributeIterator::Save (void)
+{
+  Iterate ();
+}
+
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/attribute-iterator.h	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,65 @@
+#ifndef ATTRIBUTE_ITERATOR_H
+#define ATTRIBUTE_ITERATOR_H
+
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include <vector>
+
+namespace ns3 {
+
+class ObjectVectorValue;
+
+// This class is used internally by ConfigStore and GtkConfigStore.
+class AttributeIterator
+{
+public:
+  AttributeIterator ();
+  virtual ~AttributeIterator ();
+
+  void Iterate (void);
+protected:
+  std::string GetCurrentPath (void) const;
+private:
+  virtual void DoVisitAttribute (Ptr<Object> object, std::string name) = 0;
+  virtual void DoStartVisitObject (Ptr<Object> object);
+  virtual void DoEndVisitObject (void);
+  virtual void DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value);
+  virtual void DoEndVisitPointerAttribute (void);
+  virtual void DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector);
+  virtual void DoEndVisitArrayAttribute (void);
+  virtual void DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item);
+  virtual void DoEndVisitArrayItem (void);
+
+  void DoIterate (Ptr<Object> object);
+  bool IsExamined (Ptr<const Object> object);
+  std::string GetCurrentPath (std::string attr) const;
+
+  void VisitAttribute (Ptr<Object> object, std::string name);
+  void StartVisitObject (Ptr<Object> object);
+  void EndVisitObject (void);
+  void StartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value);
+  void EndVisitPointerAttribute (void);
+  void StartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector);
+  void EndVisitArrayAttribute (void);
+  void StartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item);
+  void EndVisitArrayItem (void);
+
+
+  std::vector<Ptr<Object> > m_examined;
+  std::vector<std::string> m_currentPath;
+};
+
+class TextFileAttributeIterator : public AttributeIterator
+{
+public:
+  TextFileAttributeIterator (std::ostream &os);
+  void Save (void);
+private:
+  virtual void DoVisitAttribute (Ptr<Object> object, std::string name);
+  std::ostream &m_os;
+};
+
+
+} // namespace ns3
+
+#endif /* ATTRIBUTE_ITERATOR_H */
--- a/src/contrib/config-store.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/contrib/config-store.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -1,9 +1,9 @@
 #include "config-store.h"
+#include "attribute-iterator.h"
 #include "ns3/string.h"
+#include "ns3/log.h"
+#include "ns3/attribute-list.h"
 #include "ns3/config.h"
-#include "ns3/object-vector.h"
-#include "ns3/pointer.h"
-#include "ns3/log.h"
 #include <string>
 #include <fstream>
 #include <iostream>
@@ -54,141 +54,22 @@
   while (is.good())
     {
       is >> path >> value;
-      NS_LOG_DEBUG (path << "=" << value);
+      NS_LOG_DEBUG (path << " " << value);
       Config::Set (path, StringValue (value));
     }
 }
 void 
 ConfigStore::StoreTo (std::string filename)
 {
+
   std::ofstream os;
   os.open (filename.c_str (), std::ios::out);
-  for (uint32_t i = 0; i < Config::GetRootNamespaceObjectN (); ++i)
-    {
-      Ptr<Object> object = Config::GetRootNamespaceObject (i);
-      Store (os, object);
-    }
+  TextFileAttributeIterator iter = TextFileAttributeIterator (os);
+  iter.Save ();
   os.close ();
-  NS_ASSERT (m_currentPath.empty ());
-  NS_ASSERT (m_examined.empty ());
   exit (0);
 }
 
-bool
-ConfigStore::IsExamined (Ptr<const Object> object)
-{
-  for (uint32_t i = 0; i < m_examined.size (); ++i)
-    {
-      if (object == m_examined[i])
-	{
-	  return true;
-	}
-    }
-  return false;
-}
-
-std::string
-ConfigStore::GetCurrentPath (std::string attr) const
-{
-  std::ostringstream oss;
-  for (uint32_t i = 0; i < m_currentPath.size (); ++i)
-    {
-      oss << "/" << m_currentPath[i];
-    }
-  oss << "/" << attr;
-  return oss.str ();
-}
-
-void
-ConfigStore::Store (std::ostream &os, Ptr<const Object> object)
-{
-  if (IsExamined (object))
-    {
-      return;
-    }
-  TypeId tid = object->GetInstanceTypeId ();
-  m_currentPath.push_back ("$" + tid.GetName ());
-  NS_LOG_DEBUG ("store " << tid.GetName ());
-  for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
-    {
-      Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
-      const PointerChecker *ptrChecker = dynamic_cast<const PointerChecker *> (PeekPointer (checker));
-      if (ptrChecker != 0)
-	{
-	  NS_LOG_DEBUG ("pointer attribute " << tid.GetAttributeName (i));
-	  PointerValue ptr;
-	  object->GetAttribute (tid.GetAttributeName (i), ptr);
-	  Ptr<const Object> tmp = ptr.Get<Object> ();
-	  if (tmp != 0)
-	    {
-	      m_currentPath.push_back (tid.GetAttributeName (i));
-	      m_examined.push_back (object);
-	      Store (os, tmp);
-	      m_examined.pop_back ();
-	      m_currentPath.pop_back ();
-	    }
-	  continue;
-	}
-      // attempt to cast to an object vector.
-      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (checker));
-      if (vectorChecker != 0)
-	{
-	  NS_LOG_DEBUG ("vector attribute " << tid.GetAttributeName (i));
-	  ObjectVectorValue vector;
-	  object->GetAttribute (tid.GetAttributeName (i), vector);
-	  for (uint32_t j = 0; j < vector.GetN (); ++j)
-	    {
-	      NS_LOG_DEBUG ("vector attribute item " << j);
-	      Ptr<const Object> tmp = vector.Get (j);
-	      std::ostringstream oss;
-	      oss << tid.GetAttributeName (i) << "/" << j;
-	      m_currentPath.push_back (oss.str ());
-	      m_examined.push_back (object);
-	      Store (os, tmp);
-	      m_examined.pop_back ();
-	      m_currentPath.pop_back ();
-	    }
-	  continue;
-	}
-      uint32_t flags = tid.GetAttributeFlags (i);
-      Ptr<const AttributeAccessor> accessor = tid.GetAttributeAccessor (i);
-      if ((flags & TypeId::ATTR_GET) && accessor->HasGetter () &&
-	  (flags & TypeId::ATTR_SET) && accessor->HasSetter ())
-	{
-	  StringValue str;
-	  object->GetAttribute (tid.GetAttributeName (i), str);
-	  os << GetCurrentPath (tid.GetAttributeName (i)) << " " << str.Get () << std::endl;
-	}
-      else
-	{
-	  NS_LOG_DEBUG ("could not store " << tid.GetAttributeName (i));
-	}
-    }
-  Object::AggregateIterator iter = object->GetAggregateIterator ();
-  bool recursiveAggregate = false;
-  while (iter.HasNext ())
-    {
-      Ptr<const Object> tmp = iter.Next ();
-      if (IsExamined (tmp))
-	{
-	  recursiveAggregate = true;
-	}
-    }
-  if (!recursiveAggregate)
-    {
-      iter = object->GetAggregateIterator ();
-      while (iter.HasNext ())
-	{
-	  Ptr<const Object> tmp = iter.Next ();
-	  m_examined.push_back (object);
-	  Store (os, tmp);
-	  m_examined.pop_back ();
-	}
-    }
-  m_currentPath.pop_back ();
-}
-
-
 void 
 ConfigStore::Configure (void)
 {
--- a/src/contrib/config-store.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/contrib/config-store.h	Wed Jun 04 17:19:32 2008 -0400
@@ -2,14 +2,26 @@
 #define CONFIG_STORE_H
 
 #include "ns3/object-base.h"
-#include "ns3/object.h"
-#include <vector>
 
 namespace ns3 {
 
 /**
  * \brief Store and load simulation attribute configuration
  *
+ * While it is possible to generate a sample config file and lightly
+ * edit it to change a couple of values, there are cases where this
+ * process will not work because the same value on the same object
+ * can appear multiple times in the same automatically-generated 
+ * configuration file under different configuration paths.
+ *
+ * As such, the best way to use this class is to use it to generate
+ * an initial configuration file, extract from that configuration
+ * file only the strictly necessary elements, and move these minimal
+ * elements to a new configuration file which can then safely
+ * be edited. Another option is to use the ns3::GtkConfigStore class
+ * which will allow you to edit the parameters and will generate 
+ * configuration files where all the instances of the same parameter
+ * are changed.
  */
 class ConfigStore : public ObjectBase
 {
@@ -29,14 +41,9 @@
 private:
   void LoadFrom (std::string filename);
   void StoreTo (std::string filename);
-  void Store (std::ostream &os, Ptr<const Object> object);
-  bool IsExamined (Ptr<const Object> object);
-  std::string GetCurrentPath (std::string attr) const;
 
   std::string m_loadFilename;
   std::string m_storeFilename;
-  std::vector<Ptr<const Object> > m_examined;
-  std::vector<std::string> m_currentPath;
 };
 
 }  // namespace ns3
--- a/src/contrib/delay-jitter-estimation.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/contrib/delay-jitter-estimation.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -2,61 +2,77 @@
 #include "delay-jitter-estimation.h"
 #include "ns3/tag.h"
 #include "ns3/simulator.h"
+#include "ns3/string.h"
 
-namespace {
+namespace ns3 {
 
-class TimestampTag : public ns3::Tag
+class DelayJitterEstimationTimestampTag : public Tag
 {
 public:
-  TimestampTag ();
-  static uint32_t GetUid (void);
-  void Print (std::ostream &os) const;
-  void Serialize (ns3::Buffer::Iterator start) const;
-  uint32_t Deserialize (ns3::Buffer::Iterator start);
-  uint32_t GetSerializedSize (void) const;
+  DelayJitterEstimationTimestampTag ();
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
 
-  ns3::Time GetTxTime (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
+  Time GetTxTime (void) const;
 private:
   uint64_t m_creationTime;
 };
 
-TimestampTag::TimestampTag ()
-  : m_creationTime (ns3::Simulator::Now ().GetTimeStep ())
+DelayJitterEstimationTimestampTag::DelayJitterEstimationTimestampTag ()
+  : m_creationTime (Simulator::Now ().GetTimeStep ())
 {}
-uint32_t 
-TimestampTag::GetUid (void)
+
+TypeId 
+DelayJitterEstimationTimestampTag::GetTypeId (void)
 {
-  static uint32_t uid = ns3::Tag::AllocateUid<TimestampTag> ("mathieu.paper.TimestampTag");
-  return uid;
+  static TypeId tid = TypeId ("anon::DelayJitterEstimationTimestampTag")
+    .SetParent<Tag> ()
+    .AddConstructor<DelayJitterEstimationTimestampTag> ()
+    .AddAttribute ("CreationTime",
+		   "The time at which the timestamp was created",
+		   StringValue ("0.0s"),
+		   MakeTimeAccessor (&DelayJitterEstimationTimestampTag::GetTxTime),
+		   MakeTimeChecker ())
+    ;
+  return tid;
 }
-void 
-TimestampTag::Print (std::ostream &os) const
+TypeId 
+DelayJitterEstimationTimestampTag::GetInstanceTypeId (void) const
 {
-  os << ns3::TimeStep (m_creationTime);
+  return GetTypeId ();
+}
+
+uint32_t 
+DelayJitterEstimationTimestampTag::GetSerializedSize (void) const
+{
+  return 8;
 }
 void 
-TimestampTag::Serialize (ns3::Buffer::Iterator start) const
-{}
-uint32_t 
-TimestampTag::Deserialize (ns3::Buffer::Iterator start)
+DelayJitterEstimationTimestampTag::Serialize (TagBuffer i) const
 {
-  return 0;
+  i.WriteU64 (m_creationTime);
 }
-uint32_t 
-TimestampTag::GetSerializedSize (void) const
+void 
+DelayJitterEstimationTimestampTag::Deserialize (TagBuffer i)
 {
-  return 0;
+  m_creationTime = i.ReadU64 ();
 }
-ns3::Time 
-TimestampTag::GetTxTime (void) const
+void 
+DelayJitterEstimationTimestampTag::Print (std::ostream &os) const
 {
-  return ns3::TimeStep (m_creationTime);
+  os << "CreationTime=" << m_creationTime;
 }
-
+Time 
+DelayJitterEstimationTimestampTag::GetTxTime (void) const
+{
+  return TimeStep (m_creationTime);
 }
 
-namespace ns3 {
-
 DelayJitterEstimation::DelayJitterEstimation ()
   : m_previousRx (Simulator::Now ()),
     m_previousRxTx (Simulator::Now ()),
@@ -66,15 +82,15 @@
 void 
 DelayJitterEstimation::PrepareTx (Ptr<const Packet> packet)
 {
-  TimestampTag tag;
+  DelayJitterEstimationTimestampTag tag;
   packet->AddTag (tag);
 }
 void 
 DelayJitterEstimation::RecordRx (Ptr<const Packet> packet)
 {
-  TimestampTag tag;
+  DelayJitterEstimationTimestampTag tag;
   bool found;
-  found = packet->PeekTag (tag);
+  found = packet->FindFirstMatchingTag (tag);
   if (!found)
     {
       return;
--- a/src/contrib/delay-jitter-estimation.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/contrib/delay-jitter-estimation.h	Wed Jun 04 17:19:32 2008 -0400
@@ -7,7 +7,7 @@
 namespace ns3 {
 
 /**
- * \brief quick and diry delay and jitter estimation
+ * \brief quick and dirty delay and jitter estimation
  *
  */
 class DelayJitterEstimation
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/gtk-config-store.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,538 @@
+#include "gtk-config-store.h"
+#include "attribute-iterator.h"
+#include "ns3/config.h"
+#include "ns3/string.h"
+#include "ns3/pointer.h"
+#include "ns3/log.h"
+#include <gtk/gtk.h>
+#include <fstream>
+
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("GtkconfigStore");
+
+enum {
+  COL_NODE = 0,
+  COL_LAST
+};
+
+struct ModelNode
+{
+  enum {
+    // store object + attribute name
+    NODE_ATTRIBUTE,
+    // store object + attribute name
+    NODE_POINTER,
+    // store object + attribute name
+    NODE_VECTOR,
+    // store index + value (object)
+    NODE_VECTOR_ITEM,
+    // store object
+    NODE_OBJECT
+  } type;
+  std::string name;
+  Ptr<Object> object;
+  uint32_t index;
+};
+
+class ModelCreator : public AttributeIterator
+{
+public:
+  ModelCreator ();
+
+  void Build (GtkTreeStore *treestore);
+private:
+  virtual void DoVisitAttribute (Ptr<Object> object, std::string name);
+  virtual void DoStartVisitObject (Ptr<Object> object);
+  virtual void DoEndVisitObject (void);
+  virtual void DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value);
+  virtual void DoEndVisitPointerAttribute (void);
+  virtual void DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector);
+  virtual void DoEndVisitArrayAttribute (void);
+  virtual void DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item);
+  virtual void DoEndVisitArrayItem (void);
+  void Add (ModelNode *node);
+  void Remove (void);
+
+  GtkTreeStore *m_treestore;
+  std::vector<GtkTreeIter *> m_iters;
+};
+
+ModelCreator::ModelCreator ()
+{}
+void 
+ModelCreator::Build (GtkTreeStore *treestore)
+{
+  m_treestore = treestore;
+  m_iters.push_back (NULL);
+  Iterate ();
+  NS_ASSERT (m_iters.size () == 1);
+}
+
+
+void
+ModelCreator::Add (ModelNode *node)
+{
+  GtkTreeIter *parent = m_iters.back ();
+  GtkTreeIter *current = g_new (GtkTreeIter, 1);
+  gtk_tree_store_append (m_treestore, current, parent);
+  gtk_tree_store_set (m_treestore, current,
+		      COL_NODE, node,
+                     -1);
+  m_iters.push_back (current);
+}
+void
+ModelCreator::Remove (void)
+{
+  GtkTreeIter *iter = m_iters.back ();
+  g_free (iter);
+  m_iters.pop_back ();
+}
+
+void 
+ModelCreator::DoVisitAttribute (Ptr<Object> object, std::string name)
+{
+  ModelNode *node = new ModelNode ();
+  node->type = ModelNode::NODE_ATTRIBUTE;
+  node->object = object;
+  node->name = name;
+  Add (node);
+  Remove ();
+}
+void 
+ModelCreator::DoStartVisitObject (Ptr<Object> object)
+{
+  ModelNode *node = new ModelNode ();
+  node->type = ModelNode::NODE_OBJECT;
+  node->object = object;
+  Add (node);
+}
+void 
+ModelCreator::DoEndVisitObject (void)
+{
+  Remove ();
+}
+void 
+ModelCreator::DoStartVisitPointerAttribute (Ptr<Object> object, std::string name, Ptr<Object> value)
+{
+  ModelNode *node = new ModelNode ();
+  node->type = ModelNode::NODE_POINTER;
+  node->object = object;
+  node->name = name;
+  Add (node);
+}
+void 
+ModelCreator::DoEndVisitPointerAttribute (void)
+{
+  Remove ();
+}
+void 
+ModelCreator::DoStartVisitArrayAttribute (Ptr<Object> object, std::string name, const ObjectVectorValue &vector)
+{
+  ModelNode *node = new ModelNode ();
+  node->type = ModelNode::NODE_VECTOR;
+  node->object = object;
+  node->name = name;
+  Add (node);
+}
+void 
+ModelCreator::DoEndVisitArrayAttribute (void)
+{
+  Remove ();
+}
+void 
+ModelCreator::DoStartVisitArrayItem (const ObjectVectorValue &vector, uint32_t index, Ptr<Object> item)
+{
+  GtkTreeIter *parent = m_iters.back ();
+  GtkTreeIter *current = g_new (GtkTreeIter, 1);
+  ModelNode *node = new ModelNode ();
+  node->type = ModelNode::NODE_VECTOR_ITEM;
+  node->object = item;
+  node->index = index;
+  gtk_tree_store_append (m_treestore, current, parent);
+  gtk_tree_store_set (m_treestore, current,
+		      COL_NODE, node,
+                     -1);
+  m_iters.push_back (current);
+}
+void 
+ModelCreator::DoEndVisitArrayItem (void)
+{
+  GtkTreeIter *iter = m_iters.back ();
+  g_free (iter);
+  m_iters.pop_back ();  
+}
+
+static void
+cell_data_function_col_1 (GtkTreeViewColumn *col,
+			  GtkCellRenderer   *renderer,
+			  GtkTreeModel      *model,
+			  GtkTreeIter       *iter,
+			  gpointer           user_data)
+{
+  ModelNode *node;
+  gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
+  if (node->type == ModelNode::NODE_ATTRIBUTE)
+    {
+      StringValue str;
+      node->object->GetAttribute (node->name, str);
+      g_object_set(renderer, "text", str.Get ().c_str (), NULL);
+      g_object_set(renderer, "editable", TRUE, NULL);
+    }
+  else
+    {
+      g_object_set(renderer, "text", "", NULL);
+      g_object_set(renderer, "editable", FALSE, NULL);
+    }
+}
+
+static void
+cell_data_function_col_0 (GtkTreeViewColumn *col,
+			  GtkCellRenderer   *renderer,
+			  GtkTreeModel      *model,
+			  GtkTreeIter       *iter,
+			  gpointer           user_data)
+{
+  ModelNode *node;
+  gtk_tree_model_get (model, iter, COL_NODE, &node, -1);
+  g_object_set (renderer, "editable", FALSE, NULL);
+  switch (node->type) {
+  case ModelNode::NODE_OBJECT:
+    g_object_set(renderer, "text", node->object->GetInstanceTypeId ().GetName ().c_str (), NULL);
+    break;
+  case ModelNode::NODE_POINTER:
+    g_object_set(renderer, "text", node->name.c_str (), NULL);
+    break;
+  case ModelNode::NODE_VECTOR:
+    g_object_set(renderer, "text", node->name.c_str (), NULL);
+    break;
+  case ModelNode::NODE_VECTOR_ITEM: {
+    std::stringstream oss;
+    oss << node->index;
+    g_object_set(renderer, "text", oss.str ().c_str (), NULL);
+  } break;
+  case ModelNode::NODE_ATTRIBUTE:
+    g_object_set(renderer, "text", node->name.c_str (), NULL);
+    break;
+  }
+}
+
+
+static void
+cell_edited_callback (GtkCellRendererText *cell,
+		      gchar               *path_string,
+		      gchar               *new_text,
+		      gpointer             user_data)
+{
+  GtkTreeModel *model = GTK_TREE_MODEL (user_data);
+  GtkTreeIter iter;
+  gtk_tree_model_get_iter_from_string (model, &iter, path_string);
+  ModelNode *node;
+  gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
+  NS_ASSERT (node->type == ModelNode::NODE_ATTRIBUTE);
+  node->object->SetAttribute (node->name, StringValue (new_text));
+}
+
+static int
+get_col_number_from_tree_view_column (GtkTreeViewColumn *col)
+{
+  GList *cols;
+  int   num;
+  g_return_val_if_fail ( col != NULL, -1 );
+  g_return_val_if_fail ( col->tree_view != NULL, -1 );
+  cols = gtk_tree_view_get_columns(GTK_TREE_VIEW(col->tree_view));
+  num = g_list_index(cols, (gpointer) col);
+  g_list_free(cols);
+  return num;
+}
+
+static gboolean
+cell_tooltip_callback (GtkWidget  *widget,
+		       gint        x,
+		       gint        y,
+		       gboolean    keyboard_tip,
+		       GtkTooltip *tooltip,
+		       gpointer    user_data)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GtkTreeViewColumn * column;
+  if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (widget), 
+					  &x, &y, keyboard_tip,
+					  &model, NULL, &iter))
+    {
+      return FALSE;
+    }
+  if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget),
+				      x, y, NULL, &column, NULL, NULL))
+    {
+      return FALSE;
+    }  
+  int col = get_col_number_from_tree_view_column (column);
+
+  ModelNode *node;
+  gtk_tree_model_get (model, &iter, COL_NODE, &node, -1);
+
+  switch (node->type) {
+  case ModelNode::NODE_OBJECT:
+    if (col == 0)
+      {
+	std::string tip = "This object is of type " + node->object->GetInstanceTypeId ().GetName ();
+	gtk_tooltip_set_text (tooltip, tip.c_str ());
+	return TRUE;
+      }
+    break;
+  case ModelNode::NODE_POINTER:
+    if (col == 0)
+      {
+	PointerValue ptr;
+	node->object->GetAttribute (node->name, ptr);
+	std::string tip = "This object is of type " + ptr.GetObject ()->GetInstanceTypeId ().GetName ();
+	gtk_tooltip_set_text (tooltip, tip.c_str ());
+	return TRUE;
+      }
+    break;
+  case ModelNode::NODE_VECTOR:
+    break;
+  case ModelNode::NODE_VECTOR_ITEM:
+    if (col == 0)
+      {
+	std::string tip = "This object is of type " + node->object->GetInstanceTypeId ().GetName ();
+	gtk_tooltip_set_text (tooltip, tip.c_str ());
+	return TRUE;
+      }
+    break;
+  case ModelNode::NODE_ATTRIBUTE: {
+    uint32_t attrIndex = 0;
+    TypeId tid;
+    for (tid = node->object->GetInstanceTypeId (); tid.HasParent (); tid = tid.GetParent ())
+      {
+	for (uint32_t i = 0; i < tid.GetAttributeN (); ++i)
+	  {
+	    if (tid.GetAttributeName (i) == node->name)
+	      {
+		attrIndex = i;
+		goto out;
+	      }
+	  }
+      }
+    out:
+    if (col == 0)
+      {
+	std::string tip = tid.GetAttributeHelp (attrIndex);
+	gtk_tooltip_set_text (tooltip, tip.c_str ());
+      }
+    else
+      {
+	Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (attrIndex);
+	std::string tip;
+	tip = "This attribute is of type " + checker->GetValueTypeName ();
+	if (checker->HasUnderlyingTypeInformation ())
+	  {
+	    tip += " " + checker->GetUnderlyingTypeInformation ();
+	  }
+	gtk_tooltip_set_text (tooltip, tip.c_str ());
+      }
+    return TRUE;
+  } break;
+  }
+  return FALSE;
+}
+
+
+static GtkWidget *
+create_view (GtkTreeStore *model)
+{
+  GtkTreeViewColumn   *col;
+  GtkCellRenderer     *renderer;
+  GtkWidget           *view;
+
+  view = gtk_tree_view_new();
+  g_object_set (view, "has-tooltip", TRUE, NULL);
+  g_signal_connect (view, "query-tooltip", (GCallback) cell_tooltip_callback, NULL);
+  
+  gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (view), GTK_TREE_VIEW_GRID_LINES_BOTH);
+  gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
+
+  col = gtk_tree_view_column_new();
+  gtk_tree_view_column_set_title(col, "Object Attributes");
+  gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start(col, renderer, TRUE);
+  gtk_tree_view_column_set_cell_data_func(col, renderer, cell_data_function_col_0, NULL, NULL);
+  g_object_set(renderer, "editable", FALSE, NULL);
+
+  col = gtk_tree_view_column_new();
+  gtk_tree_view_column_set_title(col, "Attribute Value");
+  gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
+  renderer = gtk_cell_renderer_text_new();
+  g_signal_connect(renderer, "edited", (GCallback) cell_edited_callback, model);
+  gtk_tree_view_column_pack_start(col, renderer, TRUE);
+  gtk_tree_view_column_set_cell_data_func(col, renderer, cell_data_function_col_1, NULL, NULL);
+
+
+  gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL (model));
+
+  g_object_unref(model); /* destroy model automatically with view */
+
+
+  return view;
+}
+
+static void
+save_clicked (GtkButton *button,
+	      gpointer   user_data)
+{
+  GtkWidget *parent_window = GTK_WIDGET (user_data);
+  GtkWidget *dialog;
+
+  dialog = gtk_file_chooser_dialog_new ("Save File",
+					GTK_WINDOW (parent_window),
+					GTK_FILE_CHOOSER_ACTION_SAVE,
+					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+					NULL);
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+  gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), "config.txt");
+
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      char *filename;
+
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+      std::ofstream os;
+      os.open (filename);
+      TextFileAttributeIterator file = TextFileAttributeIterator (os);
+      file.Save ();
+      os.close ();
+      g_free (filename);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void
+load_clicked (GtkButton *button,
+	      gpointer   user_data)
+{
+  GtkWidget *parent_window = GTK_WIDGET (user_data);
+  GtkWidget *dialog;
+
+  dialog = gtk_file_chooser_dialog_new ("Open File",
+					GTK_WINDOW (parent_window),
+					GTK_FILE_CHOOSER_ACTION_OPEN,
+					GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+					GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+					NULL);
+
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      char *filename;
+
+      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+      std::ifstream is;
+      is.open (filename, std::ios::in);
+      std::string path, value;
+      while (is.good())
+	{
+	  is >> path >> value;
+	  Config::Set (path, StringValue (value));
+	}
+      g_free (filename);
+    }
+
+  gtk_widget_destroy (dialog);
+}
+
+static void 
+exit_clicked_callback (GtkButton *button,
+		       gpointer   user_data)
+{
+  gtk_main_quit ();
+}
+
+static gboolean
+delete_event_callback (GtkWidget *widget,
+		       GdkEvent  *event,
+		       gpointer   user_data)
+{
+  gtk_main_quit ();
+  return TRUE;
+}
+
+static gboolean 
+clean_model_callback (GtkTreeModel *model,
+		      GtkTreePath *path,
+		      GtkTreeIter *iter,
+		      gpointer data)
+{
+  ModelNode *node;
+  gtk_tree_model_get (GTK_TREE_MODEL (model), iter, 
+		      COL_NODE, &node, 
+		      -1);
+  delete node;
+  gtk_tree_store_set (GTK_TREE_STORE (model), iter,
+		      COL_NODE, NULL,
+		      -1);
+  return FALSE;
+}
+
+GtkConfigStore::GtkConfigStore ()
+{}
+
+void 
+GtkConfigStore::Configure (void)
+{
+  GtkWidget *window;
+  GtkWidget *view;
+  GtkWidget *scroll;
+
+  gtk_init (0, 0);
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title (GTK_WINDOW (window), "ns-3 Object attributes.");
+  gtk_window_set_default_size (GTK_WINDOW (window), 400, 600);
+  
+  g_signal_connect (window, "delete_event", (GCallback)delete_event_callback, NULL);
+
+
+  GtkTreeStore *model = gtk_tree_store_new (COL_LAST, G_TYPE_POINTER);
+  ModelCreator creator;
+  creator.Build (model);
+
+  view = create_view (model);
+  scroll = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scroll), view);
+
+  GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
+  gtk_box_pack_end (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
+  GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+  GtkWidget *save = gtk_button_new_with_label ("Save");
+  g_signal_connect (save, "clicked",  (GCallback) save_clicked, window);
+  gtk_box_pack_end (GTK_BOX (hbox), save, FALSE, FALSE, 0);
+  GtkWidget *load = gtk_button_new_with_label ("Load");
+  g_signal_connect (load, "clicked",  (GCallback) load_clicked, window);
+  gtk_box_pack_end (GTK_BOX (hbox), load, FALSE, FALSE, 0);
+  GtkWidget *exit = gtk_button_new_with_label ("Exit");
+  g_signal_connect (exit, "clicked",  (GCallback) exit_clicked_callback, NULL);
+  gtk_box_pack_end (GTK_BOX (hbox), exit, FALSE, FALSE, 0);
+
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  gtk_widget_show_all (window);
+
+  gtk_main ();
+
+  gtk_tree_model_foreach (GTK_TREE_MODEL (model), 
+			  clean_model_callback, 
+			  NULL);
+
+  gtk_widget_destroy (window);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/gtk-config-store.h	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,17 @@
+#ifndef GTK_CONFIG_STORE_H
+#define GTK_CONFIG_STORE_H
+
+namespace ns3 {
+
+class GtkConfigStore
+{
+public:
+  GtkConfigStore ();
+
+  void Configure (void);
+};
+
+
+} // namespace ns3
+
+#endif /* GTK_CONFIG_STORE_H */
--- a/src/contrib/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/contrib/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -1,11 +1,20 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+def configure(conf):
+    check = conf.create_pkgconfig_configurator()
+    check.name = 'gtk+-2.0 >= 2.12'
+    check.uselib = 'GTK_CONFIG_STORE'
+    check.mandatory = False
+    conf.env['ENABLE_GTK_CONFIG_STORE'] = check.run()
+
+
 def build(bld):
     module = bld.create_ns3_module('contrib', ['simulator'])
     module.source = [
         'event-garbage-collector.cc',
         'gnuplot.cc',
         'delay-jitter-estimation.cc',
+        'attribute-iterator.cc',
         'config-store.cc',
         ]
 
@@ -17,3 +26,8 @@
         'delay-jitter-estimation.h',
         'config-store.h',
         ]
+
+    if bld.env()['ENABLE_GTK_CONFIG_STORE']:
+        headers.source.append ('gtk-config-store.h')
+        module.source.append ('gtk-config-store.cc')
+        module.uselib = 'GTK_CONFIG_STORE'
--- a/src/core/assert.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/assert.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,7 +28,12 @@
 
 /**
  * \ingroup core
+ * \defgroup debugging Debugging
+ */
+/**
+ * \ingroup debugging
  * \defgroup assert Assert
+ *
  * \brief assert functions and macros
  *
  * The assert macros are used to verify
--- a/src/core/attribute-accessor-helper.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute-accessor-helper.h	Wed Jun 04 17:19:32 2008 -0400
@@ -24,10 +24,16 @@
 
 namespace ns3 {
 
+/**
+ * \ingroup AttributeHelper
+ */
 template <typename V, typename T1>
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1);
 
+/**
+ * \ingroup AttributeHelper
+ */
 template <typename V, typename T1, typename T2>
 Ptr<const AttributeAccessor>
 MakeAccessorHelper (T1 a1, T2 a2);
--- a/src/core/attribute-helper.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute-helper.h	Wed Jun 04 17:19:32 2008 -0400
@@ -83,8 +83,7 @@
  *
  * The simple macros are implemented in terms of the complex
  * macros and should generally be prefered over the complex macros:
- *    - \ref ATTRIBUTE_HELPER_HEADER_1,
- *    - \ref ATTRIBUTE_HELPER_HEADER_2, and,
+ *    - \ref ATTRIBUTE_HELPER_HEADER, and,
  *    - \ref ATTRIBUTE_HELPER_CPP,
  */
 
@@ -236,19 +235,10 @@
  * \ingroup AttributeHelper
  * \param type the name of the class
  *
- * This macro should be invoked from a public section of the class
- * declaration.
- */
-#define ATTRIBUTE_HELPER_HEADER_1(type)
-
-/**
- * \ingroup AttributeHelper
- * \param type the name of the class
- *
  * This macro should be invoked outside of the class
  * declaration in its public header.
  */
-#define ATTRIBUTE_HELPER_HEADER_2(type)					\
+#define ATTRIBUTE_HELPER_HEADER(type)					\
   ATTRIBUTE_VALUE_DEFINE (type);					\
   ATTRIBUTE_ACCESSOR_DEFINE (type);					\
   ATTRIBUTE_CHECKER_DEFINE (type);
--- a/src/core/attribute-list.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute-list.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -212,7 +212,7 @@
     std::string::size_type equal = str.find ("=", cur);
     if (equal == std::string::npos)
       {
-        // XXX: invalid attribute.
+        NS_FATAL_ERROR ("Error while parsing serialized attribute: \"" << str << "\"");
         break;
       }
     else
@@ -221,7 +221,7 @@
         struct TypeId::AttributeInfo info;
         if (!TypeId::LookupAttributeByFullName (name, &info))
           {
-            // XXX invalid name.
+            NS_FATAL_ERROR ("Error while parsing serialized attribute: name does not exist: \"" << name << "\"");
             break;
           }
         else
@@ -242,7 +242,7 @@
             bool ok = val->DeserializeFromString (value, info.checker);
             if (!ok)
               {
-                // XXX invalid value
+                NS_FATAL_ERROR ("Error while parsing serialized attribute: value invalid: \"" << value << "\"");
                 break;
               }
             else
--- a/src/core/attribute-list.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute-list.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \brief a container of attributes to be used during object's construction
  *        and in ns3::Object::Set.
  *
@@ -85,7 +87,6 @@
    */
   static AttributeList *GetGlobal (void);
 
-  // XXX: untested.
   std::string SerializeToString (void) const;
   bool DeserializeFromString (std::string value);
 private:
--- a/src/core/attribute-test.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute-test.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -53,7 +53,7 @@
 {
   return is;
 }
-ATTRIBUTE_HELPER_HEADER_2 (ValueClassTest);
+ATTRIBUTE_HELPER_HEADER (ValueClassTest);
 ATTRIBUTE_HELPER_CPP (ValueClassTest);
 
 class AttributeTest : public Test
@@ -167,7 +167,7 @@
 		       MakeTraceSourceAccessor (&AttributeObjectTest::m_cb))
       .AddTraceSource ("ValueSource", "help text",
 		       MakeTraceSourceAccessor (&AttributeObjectTest::m_valueSrc))
-      .AddAttribute ("Pointer", "XXX",
+      .AddAttribute ("Pointer", "help text",
                      PointerValue (),
                      MakePointerAccessor (&AttributeObjectTest::m_ptr),
                      MakePointerChecker<Derived> ())
--- a/src/core/attribute.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/attribute.h	Wed Jun 04 17:19:32 2008 -0400
@@ -33,6 +33,15 @@
 class ObjectBase;
 
 /**
+ *
+ * \ingroup core
+ * \defgroup attribute Attribute
+ */
+
+/**
+ *
+ * \ingroup attribute
+ *
  * \brief Hold a value for an Attribute.
  *
  * Instances of this class should always be wrapped into an Attribute object.
@@ -78,6 +87,8 @@
 /**
  * \brief allow setting and getting the value of an attribute.
  *
+ * \ingroup attribute
+ *
  * The goal of this class is to hide from the user how an attribute
  * is actually set or get to or from a class instance. Implementations
  * of this base class are usually provided through the MakeAccessorHelper
@@ -124,6 +135,8 @@
 /**
  * \brief Represent the type of an attribute
  *
+ * \ingroup attribute
+ *
  * Each type of attribute has an associated unique AttributeChecker
  * subclass. The type of the subclass can be safely used by users
  * to infer the type of the associated attribute. i.e., we expect
@@ -131,7 +144,7 @@
  * to detect the type of the associated attribute.
  *
  * Most subclasses of this base class are implemented by the 
- * ATTRIBUTE_HELPER_* macros.
+ * \ref ATTRIBUTE_HELPER_HEADER and \ref ATTRIBUTE_HELPER_CPP macros.
  */
 class AttributeChecker : public RefCountBase
 {
@@ -180,6 +193,11 @@
 
 };
 
+/**
+ * \brief A class for an empty attribute value
+ *
+ * \ingroup attribute
+ */
 class EmptyAttributeValue : public AttributeValue
 {
 public:
--- a/src/core/boolean.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/boolean.h	Wed Jun 04 17:19:32 2008 -0400
@@ -26,6 +26,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \brief Hold a bool native type
  *
  * \anchor bool
--- a/src/core/command-line.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/command-line.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,7 @@
 
 /**
  * \brief parse command-line arguments
+ * \ingroup core
  *
  * Instances of this class can be used to parse command-line 
  * arguments: users can register new arguments with
--- a/src/core/config.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/config.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -765,7 +765,7 @@
   // this should trigger a notification
   d1->SetAttribute ("Source", IntegerValue (-3));
   NS_TEST_ASSERT_EQUAL (m_traceNotification, -3);
-  NS_TEST_ASSERT_EQUAL (m_tracePath, "/NodeA/NodeB/NodesB/1/Source")
+  NS_TEST_ASSERT_EQUAL (m_tracePath, "/NodeA/NodeB/NodesB/1/Source");
   m_traceNotification = 0;
   m_tracePath = "";
   // this should trigger a notification
--- a/src/core/config.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/config.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,10 @@
 class Object;
 class CallbackBase;
 
+/**
+ * \brief Configuration of simulation parameters and tracing
+ * \ingroup core
+ */
 namespace Config {
 
 /**
--- a/src/core/double.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/double.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute 
+ *
  * \class ns3::DoubleValue
  * \brief Hold an floating point type
  *
--- a/src/core/empty.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/empty.h	Wed Jun 04 17:19:32 2008 -0400
@@ -2,6 +2,9 @@
 #define EMPTY_H
 
 namespace ns3 {
+/**
+ * \brief make Callback use a separate empty type
+ */
 class empty {};
 }
 
--- a/src/core/enum.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/enum.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \brief hold variables of type 'enum'
  *
  * This class can be used to hold variables of any kind
--- a/src/core/fatal-error.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/fatal-error.h	Wed Jun 04 17:19:32 2008 -0400
@@ -24,8 +24,7 @@
 #include <iostream>
 
 /**
- * \ingroup core
- * \defgroup error Error
+ * \ingroup debugging
  * \brief fatal error handling
  *
  * \param msg message to output when this macro is hit.
--- a/src/core/global-value.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/global-value.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup Core
+ *
  * \brief hold a so-called 'global value'.
  *
  * Instances of this class are expected to be allocated as static 
--- a/src/core/integer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/integer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,7 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
  * \class ns3::IntegerValue
  * \brief Hold a signed integer type
  *
--- a/src/core/log.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/log.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,7 +28,7 @@
 
 
 /**
- * \ingroup core
+ * \ingroup debugging
  * \defgroup logging Logging
  * \brief Logging functions and macros
  *
@@ -69,7 +69,7 @@
 #define NS_LOG_COMPONENT_DEFINE(name)                           \
   static ns3::LogComponent g_log = ns3::LogComponent (name)
 
-#define APPEND_TIME_PREFIX                                      \
+#define NS_LOG_APPEND_TIME_PREFIX                               \
   if (g_log.IsEnabled (ns3::LOG_PREFIX_TIME))                   \
     {                                                           \
       LogTimePrinter printer = LogGetTimePrinter ();            \
@@ -80,13 +80,17 @@
         }                                                       \
     }
 
-#define APPEND_FUNC_PREFIX                                      \
+#define NS_LOG_APPEND_FUNC_PREFIX                               \
   if (g_log.IsEnabled (ns3::LOG_PREFIX_FUNC))                   \
     {                                                           \
       std::clog << g_log.Name () << ":" <<                      \
         __FUNCTION__ << "(): ";                                 \
     }                                                           \
 
+#ifndef NS_LOG_APPEND_CONTEXT
+#define NS_LOG_APPEND_CONTEXT
+#endif /* NS_LOG_APPEND_CONTEXT */
+
 
 /**
  * \ingroup logging
@@ -107,8 +111,9 @@
     {                                                           \
       if (g_log.IsEnabled (level))                              \
         {                                                       \
-          APPEND_TIME_PREFIX;                                   \
-          APPEND_FUNC_PREFIX;                                   \
+          NS_LOG_APPEND_TIME_PREFIX;                            \
+          NS_LOG_APPEND_CONTEXT;                                \
+          NS_LOG_APPEND_FUNC_PREFIX;                            \
           std::clog << msg << std::endl;                        \
         }                                                       \
     }                                                           \
@@ -160,7 +165,8 @@
     {                                                           \
       if (g_log.IsEnabled (ns3::LOG_FUNCTION))                  \
         {                                                       \
-          APPEND_TIME_PREFIX;                                   \
+          NS_LOG_APPEND_TIME_PREFIX;                            \
+          NS_LOG_APPEND_CONTEXT;                                \
           std::clog << g_log.Name () << ":"                     \
                     << __FUNCTION__ << "()" << std::endl;       \
         }                                                       \
@@ -189,7 +195,8 @@
     {                                                   \
       if (g_log.IsEnabled (ns3::LOG_FUNCTION))          \
         {                                               \
-          APPEND_TIME_PREFIX;                           \
+          NS_LOG_APPEND_TIME_PREFIX;                    \
+          NS_LOG_APPEND_CONTEXT;                        \
           std::clog << g_log.Name () << ":"             \
                     << __FUNCTION__ << "(";             \
           ParameterLogger (std::clog)  << parameters;   \
@@ -320,12 +327,10 @@
   bool IsNoneEnabled (void) const;
   void Enable (enum LogLevel level);
   void Disable (enum LogLevel level);
-  bool Decorate (void) const;
   char const *Name (void) const;
 private:
   int32_t     m_levels;
   char const *m_name;
-  bool        m_decorate;
 };
 
 class ParameterLogger : public std::ostream
--- a/src/core/object-base.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object-base.h	Wed Jun 04 17:19:32 2008 -0400
@@ -42,6 +42,8 @@
 class AttributeList;
 
 /**
+ * \ingroup object
+ *
  * \brief implement the ns-3 type and attribute system
  *
  * Every class which wants to integrate in the ns-3 type and attribute
--- a/src/core/object-factory.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object-factory.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 class AttributeValue;
 
 /**
+ * \ingroup object
+ *
  * \brief instantiate subclasses of ns3::Object.
  *
  * This class can also hold a set of attributes to set
@@ -77,7 +79,6 @@
   template <typename T>
   Ptr<T> Create (void) const;
 
-  ATTRIBUTE_HELPER_HEADER_1 (ObjectFactory);
 private:
   friend std::ostream & operator << (std::ostream &os, const ObjectFactory &factory);
   friend std::istream & operator >> (std::istream &is, ObjectFactory &factory);
@@ -94,7 +95,7 @@
  * \brief hold objects of type ns3::ObjectFactory
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (ObjectFactory);
+ATTRIBUTE_HELPER_HEADER (ObjectFactory);
 
 } // namespace ns3
 
--- a/src/core/object-vector.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object-vector.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -34,8 +34,16 @@
 std::string 
 ObjectVectorValue::SerializeToString (Ptr<const AttributeChecker> checker) const
 {
-  // XXX
-  return "";
+  std::ostringstream oss;
+  for (uint32_t i = 0; i < m_objects.size (); ++i)
+    {
+      oss << m_objects[i];
+      if (i != m_objects.size () - 1)
+	{
+	  oss << " ";
+	}
+    }
+  return oss.str ();
 }
 bool 
 ObjectVectorValue::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
--- a/src/core/object-vector.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object-vector.h	Wed Jun 04 17:19:32 2008 -0400
@@ -9,6 +9,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup object
+ * 
  * \brief contain a vector of ns3::Object pointers.
  *
  * This class it used to get attribute access to an array of
--- a/src/core/object.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -375,7 +375,7 @@
   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<DerivedA> (), 0);
   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
   NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<DerivedB> (), 0);
-  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0)
+  NS_TEST_ASSERT_UNEQUAL (baseB->GetObject<BaseB> (), 0);
 
   baseA = CreateObject<BaseA> ();
   baseB = CreateObject<BaseB> ();
--- a/src/core/object.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/object.h	Wed Jun 04 17:19:32 2008 -0400
@@ -39,8 +39,21 @@
 class TraceSourceAccessor;
 
 /**
+ * \ingroup core
+ * \defgroup object Object
+ */
+/**
+ * \ingroup object
  * \brief a base class which provides memory management and object aggregation
  *
+ * The memory management scheme is based on reference-counting with dispose-like
+ * functionality to break the reference cycles. The reference count is increamented
+ * and decremented with the methods Object::Ref and Object::Unref. If a reference cycle is
+ * present, the user is responsible for breaking it by calling Object::Dispose in
+ * a single location. This will eventually trigger the invocation of Object::DoDispose 
+ * on itself and all its aggregates. The Object::DoDispose method is always automatically
+ * invoked from the Object::Unref method before destroying the object, even if the user 
+ * did not call Object::Dispose directly.
  */
 class Object : public ObjectBase
 {
--- a/src/core/pointer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/pointer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -26,6 +26,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \brief hold objects of type Ptr<T>
  */
 class PointerValue : public AttributeValue
--- a/src/core/ptr.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/ptr.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,12 @@
 namespace ns3 {
 
 /**
+ * \ingroup core
+ * \defgroup ptr Smart Pointer
+ */
+/**
+ * \ingroup ptr
+ *
  * \brief smart pointer class similar to boost::intrusive_ptr
  *
  * This smart-pointer class assumes that the underlying
--- a/src/core/singleton.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/singleton.h	Wed Jun 04 17:19:32 2008 -0400
@@ -22,6 +22,17 @@
 
 namespace ns3 {
 
+/**
+ * \brief a template singleton
+ *
+ * This template class can be used to implement the singleton pattern.
+ * The underlying object will be destroyed automatically when the process
+ * exits. Note that, if you call Singleton::Get again after the object has
+ * been destroyed, the object will be re-created which will result in a
+ * memory leak as reported by most memory leak checkers. It is up to the
+ * user to ensure that Singleton::Get is never called from a static variable
+ * finalizer.
+ */
 template <typename T>
 class Singleton
 {
--- a/src/core/string.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/string.h	Wed Jun 04 17:19:32 2008 -0400
@@ -7,6 +7,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \class ns3::StringValue
  * \brief hold variables of type string
  *
--- a/src/core/test.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/test.h	Wed Jun 04 17:19:32 2008 -0400
@@ -33,6 +33,12 @@
 class TestManager;
 
 /**
+ * \ingroup core
+ * \defgroup test Test
+ */
+/**
+ * \ingroup test
+ *
  * \brief base class for new regressions tests
  *
  * To add a new regression test, you need to:
@@ -65,6 +71,8 @@
 };
 
 /**
+ * \ingroup test
+ *
  * \brief gather and run all regression tests
  */
 class TestManager {
@@ -100,6 +108,42 @@
 };
 }; // namespace ns3 
 
+#define NS_TEST_ASSERT_EQUAL_FILELINE(got, expected, file, line)    \
+  do {                                                              \
+    if ((got) != (expected))                                        \
+      {                                                             \
+        Failure () << file << ":" <<line                            \
+                   << ": expected " << (expected)                   \
+                   << ", got " << (got) << std::endl;               \
+        result = false;                                             \
+      }                                                             \
+  } while (false)
+
+#define NS_TEST_ASSERT_UNEQUAL_FILELINE(got, expected,file,line)    \
+  do {                                                              \
+    if ((got) == (expected))                                        \
+      {                                                             \
+        Failure () << file << ":" <<line                            \
+                   << ": did not want " << (expected)               \
+                   << ", got " << (got) << std::endl;               \
+        result = false;                                             \
+      }                                                             \
+  } while (false)
+
+
+#define NS_TEST_ASSERT_FILELINE(assertion, file, line)  \
+  do {                                                  \
+    if (!(assertion))                                   \
+      {                                                 \
+        Failure () << file << ":" <<line                \
+                   << ": assertion `" << #assertion     \
+                   << "' failed." << std::endl;         \
+        result = false;                                 \
+      }                                                 \
+  } while (false)
+
+
+
 /**
  * Convenience macro to check that a value returned by a test is what
  * is expected.  Note: this macro assumes a 'bool result = true'
@@ -110,13 +154,8 @@
  * \param expected value that the test is expected to return
  */
 #define NS_TEST_ASSERT_EQUAL(got, expected)             \
-    if ((got) != (expected))                            \
-      {                                                 \
-        Failure () << __FILE__ << ":" <<__LINE__        \
-                   << ": expected " << (expected)       \
-                   << ", got " << (got) << std::endl;   \
-        result = false;                                 \
-      }
+  NS_TEST_ASSERT_EQUAL_FILELINE(got,expected,__FILE__,__LINE__)
+
 /**
  * Convenience macro to check that a value returned by a test is what
  * is expected.  Note: this macro assumes a 'bool result = true'
@@ -127,13 +166,8 @@
  * \param expected value that the test is expected to return
  */
 #define NS_TEST_ASSERT_UNEQUAL(got, expected)           \
-    if ((got) == (expected))                            \
-      {                                                 \
-        Failure () << __FILE__ << ":" <<__LINE__        \
-                   << ": did not want " << (expected)   \
-                   << ", got " << (got) << std::endl;   \
-        result = false;                                 \
-      }
+  NS_TEST_ASSERT_UNEQUAL_FILELINE(got,expected,__FILE__,__LINE__)
+
 /**
  * Convenience macro to check an assertion is held during an unit
  * test.  Note: this macro assumes a 'bool result = true' declaration
@@ -143,13 +177,7 @@
  * \param assertion expression that must be true if the test did not fail
  */
 #define NS_TEST_ASSERT(assertion)                       \
-    if (!(assertion))                                   \
-      {                                                 \
-        Failure () << __FILE__ << ":" <<__LINE__        \
-                   << ": assertion `" << #assertion     \
-                   << "' failed." << std::endl;         \
-        result = false;                                 \
-      }
+  NS_TEST_ASSERT_FILELINE (assertion, __FILE__,__LINE__)
 
 
 #endif /* RUN_SELF_TESTS */
--- a/src/core/trace-source-accessor.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/trace-source-accessor.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 class ObjectBase;
 
 /**
+ * \ingroup tracing
+ *
  * \brief control access to objects' trace sources
  *
  * This class abstracts the kind of trace source to which we want to connect
@@ -72,7 +74,10 @@
  * \param a the trace source
  *
  * Create a TraceSourceAccessor which will control access to the underlying
- * trace source.
+ * trace source. This helper template method assumes that the underlying
+ * type implements a statically-polymorphic set of Connect and Disconnect
+ * methods and creates a dynamic-polymorphic class to wrap the underlying
+ * static-polymorphic class.
  */
 template <typename T>
 Ptr<const TraceSourceAccessor> MakeTraceSourceAccessor (T a);
--- a/src/core/traced-value.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/traced-value.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,6 +32,13 @@
 namespace ns3 {
 
 /**
+ * \ingroup core
+ * \defgroup tracing Tracing
+ */
+
+/**
+ * \ingroup tracing
+ *
  * \brief trace classes with value semantics
  *
  * If you want to trace the change of value of a class or
@@ -40,7 +47,7 @@
  * this template: this instance will behave just like
  * the original class (if it did not export any special method),
  * and will define Connect/DisconnectWithoutContext methods to work
- * with an ns3::TraceSourceAccessor.
+ * with ns3::MakeTraceSourceAccessor.
  */
 template <typename T>
 class TracedValue
--- a/src/core/type-id.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/type-id.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -473,6 +473,12 @@
   return TypeId (parent);
 }
 bool 
+TypeId::HasParent (void) const
+{
+  uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
+  return parent != m_tid;
+}
+bool 
 TypeId::IsChildOf (TypeId other) const
 {
   TypeId tmp = *this;
--- a/src/core/type-id.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/type-id.h	Wed Jun 04 17:19:32 2008 -0400
@@ -109,6 +109,8 @@
    */
   TypeId GetParent (void) const;
 
+  bool HasParent (void) const;
+
   /**
    * \param other a parent TypeId
    * \returns true if the input TypeId is really a parent
@@ -352,7 +354,6 @@
   TypeId ();
   ~TypeId ();
 
-  ATTRIBUTE_HELPER_HEADER_1 (TypeId);
 private:
   friend class AttributeList;
   friend bool operator == (TypeId a, TypeId b);
@@ -386,7 +387,7 @@
  */
 
 
-ATTRIBUTE_HELPER_HEADER_2 (TypeId);
+ATTRIBUTE_HELPER_HEADER (TypeId);
 
 } // namespace ns3 
 
--- a/src/core/uinteger.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/core/uinteger.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 namespace ns3 {
 
 /**
+ * \ingroup attribute
+ *
  * \class ns3::UintegerValue
  * \brief Hold an unsigned integer type
  *
--- a/src/devices/csma/csma-net-device.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/csma/csma-net-device.h	Wed Jun 04 17:19:32 2008 -0400
@@ -420,7 +420,6 @@
    * fire.
    *
    * @see class CallBackTraceSource
-   * @see class TraceResolver
    */
   TracedCallback<Ptr<const Packet> > m_rxTrace;
   TracedCallback<Ptr<const Packet> > m_dropTrace;
--- a/src/devices/csma/csma.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/csma/csma.h	Wed Jun 04 17:19:32 2008 -0400
@@ -1,9 +1,134 @@
 /**
  * \ingroup devices
- * \defgroup Csma Csma Models
+ * \defgroup CSMA CSMA Model
+ *
+ * \section CSMA Model
+ *
+ * The ns-3 CSMA device models a simple bus network in the spirit of Ethernet.
+ * Although it does not model any real physical network you could ever build 
+ * or buy, it does provide some very useful functionality.
+ *
+ * Typically when one thinks of a bus network Ethernet or IEEE 802.3 comes to
+ * mind.  Ethernet uses CSMA/CD (Carrier Sense Multiple Access with Collision
+ * Detection with exponentially increasing backoff to contend for the shared 
+ * transmission medium.  The ns-3 CSMA device models only a portion of this 
+ * process, using the nature of the globally available channel to provide 
+ * instantaneous (faster than light) carrier sense and priority-based 
+ * collision "avoidance."  Collisions in the sense of Ethernet never happen and
+ * so the ns-3 CSMA device does not model collision detection, nor will any
+ * transmission in progress be "jammed."
+ *
+ * \subsection CSMA Channel Model
+ *
+ * The class ns3::CsmaChannel models the actual transmission medium.
+ * There is no fixed limit for the number of devices connected to the channel.
+ * The ns3::CsmaChannel models a bitrate and a speed-of-light delay which can
+ * be accessed via the attributes "BitRate" and "Delay" respectively.
  *
- * \section Csma Models
+ * The ns3::CsmaChannel has three states, IDLE, TRANSMITTING and PROPAGATING.
+ * These three states are "seen" instantaneously by all devices on the channel.
+ * By this we mean that if one device begins or ends a simulated transmission,
+ * all devices on the channel are immediately aware of the change in state.
+ * There is no time during which one device may see an IDLE channel while
+ * another device physically further away in the collision domain may have 
+ * begun transmitting with the associated signals not propagated.  Thus there
+ * is no need for collision detection in the ns3::CsmaChannel model and it is
+ * not implemented in any way.
+ *
+ * We do, as the name indicates, have a Carrier Sense aspect to the model.
+ * Since the simulator is single threaded, access to the common channel will
+ * be serialized by the simulator.  This provides a deterministic mechanism
+ * for contending for the channel.  The channel is allocated (transitioned from
+ * state IDLE to state TRANSMITTING) on a first-come first-served basis.  The
+ * channel always goes through a three state process:
+ *
+ *  IDLE -> TRANSMITTING -> PROPAGATING -> IDLE
+ *
+ * The TRANSMITTING state models the time during which the source net device
+ * is actually wiggling the signals on the wire.  The PROPAGATING state models
+ * the time after the last bit was sent, when the signal is propagating down 
+ * the wire to the "far end."  
+ *
+ * The transition to the TRANSMITTING state is  driven by a call to 
+ * ns3::CsmaChannel::TransmitStart which is called by the net device that 
+ * transmits the packet.  It is the responsibility of that device to end the
+ * transmission with a call to ns3::CsmaChannel::TransmitEnd at the appropriate
+ * simulation time that reflects the time elapsed to put all of the packet bits
+ * on the wire.  When TransmitEnd is called, the channel schedules an event
+ * corresponding to a single speed-of-light delay.  This delay applies to all
+ * net devices on the channel identically.  You can think of a symmetrical hub
+ * in which the packet bits propagate to a central location and then back out
+ * equal length cables to the other devices on the channel.
+ *
+ * The ns3::CsmaChannel models a broadcast medium so the packet is delivered
+ * to all of the devices on the channel (including the source) at the end of 
+ * the propagation time.
+ *
+ * \subsection CSMA Net Device Model
  *
- * The set of Csma models provides an abstrated shared media net device
- * and channel, similar to a switched ethernet.
+ * The CSMA network device appears somewhat like an Ethernet device.  The
+ * ns3::CsmaNetDevice provides following Attributes:
+ *
+ * - Address:           The ns3::Mac48Address of the device;
+ * - DataRate:          The data rate of the device;
+ * - SendEnable:        Enable packet transmission if true;
+ * - ReceiveEnable:     Enable packet reception if true;
+ * - EncapsulationMode: Type of link layer encapsulation to use;
+ * - RxErrorModel:      The receive error model;
+ * - TxQueue:           The trasmit queue used by the device;
+ * - InterframeGap:     The optional time to wait between "frames";
+ * - Rx:                A trace source for received packets;
+ * - Drop:              A trace source for dropped packets.
+ *
+ * The ns3::CsmaNetDevice supports the assignment of a "receive error model."
+ * This is an ns3::ErrorModel object that is used to simulate data corruption
+ * on the link.
+ *
+ * Packets sent over the ns3::CsmaNetDevice are always routed through the 
+ * transmit queue to provide a trace hook for packets sent out over the 
+ * network.  This transmit queue can be set (via attribute) to model different
+ * queueing strategies.
+ *
+ * Also configurable by attribute is the encapsulation method used by the
+ * device.  Every packet gets an ns3::EthernetHeader that includes the 
+ * destination and source MAC addresses, and a length/type field.  Every packet
+ * also gets an ns3::EthernetTrailer which includes the FCS.  Data in the
+ * packet may be encapsulated in different ways.  By default, or by setting
+ * the "EncapsulationMode" attribute to "Llc", the encapsulation is by 
+ * LLC SNAP.  In this case, a SNAP header is added that contains the EtherType
+ * (IP or ARP).  The other implemented encapsulation modes are IP_ARP (set
+ * "EncapsulationMode" to "IpArp") in which the length type of the Ethernet 
+ * header receives the protocol number of the packet; or ETHERNET_V1 (set
+ * "EncapsulationMode" to "EthernetV1") in which the length type of the 
+ * Ethernet header receives the length of the packet.  A "Raw" encapsulation
+ * mode is defined but not implemented -- use of the RAW mode results in an
+ * assert firing.
+ *
+ * The ns3::CsmaNetDevice implements a random exponential backoff algorithm 
+ * that is executed if the channel is determined to be busy (TRANSMITTING or
+ * PROPAGATING) when the device wants to start propagating.  This results in a
+ * random delay of up to pow (2, retries) - 1 microseconds before a retry is
+ * attempted.  The default maximum number of retries is 1000.
+ *
+ * \subsection CSMA Model Summary
+ *
+ * The ns3 CSMA model is a simplistic model of an Ethernet-like network.  It
+ * supports a Carrier-Sense function and allows for Multiple Access to a 
+ * shared medium.  It is not physical in the sense that the state of the 
+ * medium is instantaneously shared among all devices.  This means that there
+ * is no collision detection required in this model and none is implemented.
+ * There will never be a "jam" of a packet already on the medium.  Access to 
+ * the shared channel is on a first-come first-served basis as determined by 
+ * the simulator scheduler.  If the channel is determined to be busy by looking
+ * at the global state, a random exponential backoff is performed and a retry
+ * is attempted.
+ *
+ * Ns-3 Attributes provide a mechanism for setting various parameters in the 
+ * device and channel such as addresses, encapsulation modes and error model
+ * selection.  Trace hooks are provided in the usual manner.
+ *
+ * Although the ns-3 CsmaChannel and CsmaNetDevice does not model any kind of
+ * network you could build or buy, it does provide us with some useful 
+ * functionality.  You should, however, understand that it is explicitly not 
+ * Ethernet or IEEE 802.3 but an interesting subset.
  */
--- a/src/devices/point-to-point/point-to-point-channel.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/point-to-point-channel.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2007 University of Washington
+ * Copyright (c) 2007, 2008 University of Washington
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,8 +14,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Craig Dowell <craigdo@ee.washington.edu>
  */
 
 #include "point-to-point-channel.h"
@@ -36,10 +34,6 @@
   static TypeId tid = TypeId ("ns3::PointToPointChannel")
     .SetParent<Channel> ()
     .AddConstructor<PointToPointChannel> ()
-    .AddAttribute ("BitRate", "The maximum bitrate of the channel",
-                   DataRateValue (DataRate (0xffffffff)),
-                   MakeDataRateAccessor (&PointToPointChannel::m_bps),
-                   MakeDataRateChecker ())
     .AddAttribute ("Delay", "Transmission delay through the channel",
                    TimeValue (Seconds (0)),
                    MakeTimeAccessor (&PointToPointChannel::m_delay),
@@ -54,7 +48,8 @@
 PointToPointChannel::PointToPointChannel()
 : 
   Channel ("PointToPoint Channel"), 
-  m_nDevices(0)
+  m_delay (Seconds (0.)),
+  m_nDevices (0)
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -81,9 +76,10 @@
 }
 
 bool
-PointToPointChannel::TransmitStart(Ptr<Packet> p,
-                                   Ptr<PointToPointNetDevice> src,
-                                   const Time& txTime)
+PointToPointChannel::TransmitStart(
+  Ptr<Packet> p,
+  Ptr<PointToPointNetDevice> src,
+  Time txTime)
 {
   NS_LOG_FUNCTION (this << p << src);
   NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
@@ -93,12 +89,8 @@
 
   uint32_t wire = src == m_link[0].m_src ? 0 : 1;
 
-  // Here we schedule the packet receive event at the receiver,
-  // which simplifies this model quite a bit.  The channel just
-  // adds the propagation delay time
-  Simulator::Schedule (txTime + m_delay,
-                       &PointToPointNetDevice::Receive,
-                       m_link[wire].m_dst, p);
+  Simulator::Schedule (txTime + m_delay, &PointToPointNetDevice::Receive,
+    m_link[wire].m_dst, p);
   return true;
 }
 
@@ -117,20 +109,6 @@
   return m_link[i].m_src;
 }
 
-const DataRate&
-PointToPointChannel::GetDataRate (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_bps;
-}
-
-const Time&
-PointToPointChannel::GetDelay (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  return m_delay;
-}
-
 Ptr<NetDevice>
 PointToPointChannel::GetDevice (uint32_t i) const
 {
@@ -138,5 +116,4 @@
   return GetPointToPointDevice (i);
 }
 
-
 } // namespace ns3
--- a/src/devices/point-to-point/point-to-point-channel.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/point-to-point-channel.h	Wed Jun 04 17:19:32 2008 -0400
@@ -36,14 +36,7 @@
  * This class represents a very simple point to point channel.  Think full
  * duplex RS-232 or RS-422 with null modem and no handshaking.  There is no
  * multi-drop capability on this channel -- there can be a maximum of two 
- * point-to-point net devices connected.  Once we start talking about multi-
- * drop, or CSMA, or some other sharing mechanism, things begin getting 
- * complicated quickly.  Rather than invent some ad-hoc mechanism, we just
- * Keep It Simple everywhere.
- *
- * 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.  Both directions use the same speed and delay time.
+ * point-to-point net devices connected.
  *
  * There are two "wires" in the channel.  The first device connected gets the
  * [0] wire to transmit on.  The second device gets the [1] wire.  There is a
@@ -58,7 +51,7 @@
    * \brief Create a PointToPointChannel
    *
    * By default, you get a channel with the name "PointToPoint Channel" that
-   * has an "infitely" fast transmission speed and zero delay.
+   * has zero transmission delay.
    */
   PointToPointChannel ();
 
@@ -75,38 +68,32 @@
    * \param txTime Transmit time to apply
    */
   bool TransmitStart (Ptr<Packet> p, Ptr<PointToPointNetDevice> src,
-                      const Time& txTime);
+    Time txTime);
 
   /**
    * \brief Get number of devices on this channel
    * \returns number of devices on this channel
    */
   virtual uint32_t GetNDevices (void) const;
+
   /*
    * \brief Get PointToPointNetDevice corresponding to index i on this channel
    * \param i Index number of the device requested
    * \returns Ptr to PointToPointNetDevice requested
    */
   Ptr<PointToPointNetDevice> GetPointToPointDevice (uint32_t i) const;
-  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
+
   /*
-   * \brief Get reference to DataRate for this channel
-   * \returns const reference to underlying DataRate object
+   * \brief Get NetDevice corresponding to index i on this channel
+   * \param i Index number of the device requested
+   * \returns Ptr to NetDevice requested
    */
-  const DataRate& GetDataRate (void);
-  /*
-   * \brief Get reference to Time object storing the delay on this channel
-   * \returns const reference to underlying Time object
-   */
-  const Time&     GetDelay (void);
+  virtual Ptr<NetDevice> GetDevice (uint32_t i) const;
 
 private:
-
   // Each point to point link has exactly two net devices
   static const int N_DEVICES = 2;
 
-
-  DataRate      m_bps;
   Time          m_delay;
   int32_t       m_nDevices;
 
@@ -122,7 +109,7 @@
   {
   public:
     Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
-    WireState              m_state;
+    WireState                  m_state;
     Ptr<PointToPointNetDevice> m_src;
     Ptr<PointToPointNetDevice> m_dst;
   };
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2005,2006 INRIA
+ * Copyright (c) 2007, 2008 University of Washington
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,9 +14,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author:  Craig Dowell <craigdo@ee.washington.edu>
- * Revised: George Riley <riley@ece.gatech.edu>
  */
 
 #include "ns3/log.h"
@@ -48,7 +45,7 @@
                    MakeMac48AddressAccessor (&PointToPointNetDevice::m_address),
                    MakeMac48AddressChecker ())
     .AddAttribute ("DataRate", "The default data rate for point to point links",
-                   DataRateValue (DataRate ("10Mb/s")),
+                   DataRateValue (DataRate ("32768b/s")),
                    MakeDataRateAccessor (&PointToPointNetDevice::m_bps),
                    MakeDataRateChecker ())
     .AddAttribute ("ReceiveErrorModel", "XXX",
@@ -85,15 +82,10 @@
 }
 
 PointToPointNetDevice::~PointToPointNetDevice ()
-{}
-
-void 
-PointToPointNetDevice::SetAddress (Mac48Address self)
 {
-  m_address = self;
 }
 
-void 
+  void 
 PointToPointNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -103,7 +95,7 @@
   p->AddHeader (ppp);
 }
 
-bool 
+  bool 
 PointToPointNetDevice::ProcessHeader(Ptr<Packet> p, uint16_t& param)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -113,7 +105,8 @@
   return true;
 }
 
-void PointToPointNetDevice::DoDispose()
+  void 
+PointToPointNetDevice::DoDispose()
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_node = 0;
@@ -122,22 +115,21 @@
   NetDevice::DoDispose ();
 }
 
-void PointToPointNetDevice::SetDataRate(const DataRate& bps)
+  void 
+PointToPointNetDevice::SetDataRate(DataRate bps)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  if (!m_channel || bps <= m_channel->GetDataRate ())
-    {
-      m_bps = bps;
-    }
+  m_bps = bps;
 }
 
-void PointToPointNetDevice::SetInterframeGap(const Time& t)
+  void 
+PointToPointNetDevice::SetInterframeGap(Time t)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_tInterframeGap = t;
 }
 
-bool
+  bool
 PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION (this << p);
@@ -154,33 +146,40 @@
 
   NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << 
     txCompleteTime.GetSeconds () << "sec");
-  // Schedule the tx complete event
+
   Simulator::Schedule (txCompleteTime, 
-                       &PointToPointNetDevice::TransmitComplete, 
-                       this);
+    &PointToPointNetDevice::TransmitComplete, this);
+
   return m_channel->TransmitStart(p, this, txTime); 
 }
 
-void PointToPointNetDevice::TransmitComplete (void)
+  void 
+PointToPointNetDevice::TransmitComplete (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
 //
-// 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
-// get the next packet from the queue.  If the queue is empty, we are
-// done, otherwise transmit the next packet.
+// This function is called to when we're all done transmitting a packet.
+// We try and pull another packet off of the transmit queue.  If the queue
+// is empty, we are done, otherwise we need to start transmitting the
+// next packet.
 //
   NS_ASSERT_MSG(m_txMachineState == BUSY, "Must be BUSY if transmitting");
   m_txMachineState = READY;
   Ptr<Packet> p = m_queue->Dequeue ();
   if (p == 0)
     {
-      return; // Nothing to do at this point
+//
+// No packet was on the queue, so we just exit.
+//
+      return;
     }
+//
+// Got another packet off of the queue, so start the transmit process agin.
+//
   TransmitStart(p);
 }
 
-bool 
+  bool 
 PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
 {
   NS_LOG_FUNCTION (this << &ch);
@@ -188,64 +187,64 @@
   m_channel = ch;
 
   m_channel->Attach(this);
-  m_bps = m_channel->GetDataRate ();
-  // GFR Comment.  Below is definitely wrong.  Interframe gap
-  // is unrelated to channel delay.
-  // -- unlesss you want to introduce a default gap which is there to avoid
-  // parts of multiple packets flowing on the "wire" at the same time.
-  //m_tInterframeGap = m_channel->GetDelay ();
 
-  /* 
-   * For now, this device is up whenever a channel is attached to it.
-   * In fact, it should become up only when the second device
-   * is attached to the channel. So, there should be a way for
-   * a PointToPointChannel to notify both of its attached devices
-   * that the channel is 'complete', hence that the devices are
-   * up, hence that they can call NotifyLinkUp. 
-   */
+//
+// This device is up whenever it is attached to a channel.  A better plan
+// would be to have the link come up when both devices are attached, but this
+// is not done for now.
+//
   NotifyLinkUp ();
   return true;
 }
 
-void PointToPointNetDevice::SetQueue (Ptr<Queue> q)
+  void
+PointToPointNetDevice::SetQueue (Ptr<Queue> q)
 {
   NS_LOG_FUNCTION (this << q);
-
   m_queue = q;
 }
 
-void PointToPointNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
+  void
+PointToPointNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
 {
   NS_LOG_FUNCTION ("(" << em << ")");
-
   m_receiveErrorModel = em;
 }
 
-void PointToPointNetDevice::Receive (Ptr<Packet> packet)
+ void
+PointToPointNetDevice::Receive (Ptr<Packet> packet)
 {
   NS_LOG_FUNCTION (this << packet);
   uint16_t protocol = 0;
 
   if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) ) 
     {
+// 
+// If we have an error model and it indicates that it is time to lose a
+// corrupted packet, don't forward this packet up, let it go.
+//
       m_dropTrace (packet);
-      // Do not forward up; let this packet go
     }
   else 
     {
+// 
+// Hit the receive trace hook, strip off the point-to-point protocol header
+// and forward this packet up the protocol stack.
+//
       m_rxTrace (packet);
       ProcessHeader(packet, protocol);
       m_rxCallback (this, packet, protocol, GetBroadcast ());
     }
 }
 
-Ptr<Queue> PointToPointNetDevice::GetQueue(void) const 
+  Ptr<Queue> 
+PointToPointNetDevice::GetQueue(void) const 
 { 
   NS_LOG_FUNCTION_NOARGS ();
   return m_queue;
 }
 
-void
+  void
 PointToPointNetDevice::NotifyLinkUp (void)
 {
   m_linkUp = true;
@@ -255,110 +254,167 @@
     }
 }
 
-void 
+  void 
 PointToPointNetDevice::SetName(const std::string name)
 {
   m_name = name;
 }
-std::string 
+
+  std::string 
 PointToPointNetDevice::GetName(void) const
 {
   return m_name;
 }
-void 
+
+  void 
 PointToPointNetDevice::SetIfIndex(const uint32_t index)
 {
   m_ifIndex = index;
 }
-uint32_t 
+
+  uint32_t 
 PointToPointNetDevice::GetIfIndex(void) const
 {
   return m_ifIndex;
 }
-Ptr<Channel> 
+
+  Ptr<Channel> 
 PointToPointNetDevice::GetChannel (void) const
 {
   return m_channel;
 }
-Address 
+
+//
+// This is a point-to-point device, so we really don't need any kind of address
+// information.  However, the base class NetDevice wants us to define the
+// methods to get and set the address.  Rather than be rude and assert, we let
+// clients get and set the address, but simply ignore them.
+  void 
+PointToPointNetDevice::SetAddress (Mac48Address addr)
+{
+  m_address = addr;
+}
+
+  Address 
 PointToPointNetDevice::GetAddress (void) const
 {
   return m_address;
 }
-bool 
+
+  bool 
 PointToPointNetDevice::SetMtu (const uint16_t mtu)
 {
   m_mtu = mtu;
   return true;
 }
-uint16_t 
+
+  uint16_t 
 PointToPointNetDevice::GetMtu (void) const
 {
   return m_mtu;
 }
-bool 
+
+  bool 
 PointToPointNetDevice::IsLinkUp (void) const
 {
   return m_linkUp;
 }
-void 
+
+  void 
 PointToPointNetDevice::SetLinkChangeCallback (Callback<void> callback)
 {
   m_linkChangeCallback = callback;
 }
-bool 
+
+//
+// This is a point-to-point device, so every transmission is a broadcast to
+// all of the devices on the network.
+//
+  bool 
 PointToPointNetDevice::IsBroadcast (void) const
 {
   return true;
 }
-Address
+
+//
+// We don't really need any addressing information since this is a 
+// point-to-point device.  The base class NetDevice wants us to return a
+// broadcast address, so we make up something reasonable.
+//
+  Address
 PointToPointNetDevice::GetBroadcast (void) const
 {
   return Mac48Address ("ff:ff:ff:ff:ff:ff");
 }
-bool 
+
+//
+// We don't deal with multicast here.  It doesn't make sense to include some
+// of the one destinations on the network but exclude some of the others.
+  bool 
 PointToPointNetDevice::IsMulticast (void) const
 {
   return false;
 }
-Address 
+
+//
+// Since we return false in the IsMulticast call, calls to other multicast
+// related methods returns are undefined according to the base class.  So we
+// can freely make something up, which is the base of the MAC multicast
+// address space.
+//
+  Address 
 PointToPointNetDevice::GetMulticast (void) const
 {
   return Mac48Address ("01:00:5e:00:00:00");
 }
-Address 
+
+  Address 
 PointToPointNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
 {
   return Mac48Address ("01:00:5e:00:00:00");
 }
-bool 
+
+  bool 
 PointToPointNetDevice::IsPointToPoint (void) const
 {
   return true;
 }
-bool 
-PointToPointNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+
+  bool 
+PointToPointNetDevice::Send(
+  Ptr<Packet> packet, 
+  const Address &dest, 
+  uint16_t protocolNumber)
 {
   NS_LOG_FUNCTION_NOARGS ();
   NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
   NS_LOG_LOGIC ("UID is " << packet->GetUid ());
 
-  // GFR Comment. Why is this an assertion? Can't a link legitimately
-  // "go down" during the simulation?  Shouldn't we just wait for it
-  // to come back up?
-  NS_ASSERT (IsLinkUp ());
+//
+// If IsLinkUp() is false it means there is no channel to send any packet 
+// over so we just return an error.
+//
+  if (IsLinkUp () == false)
+    {
+      return false;
+    }
+
+//
+// Stick a point to point protocol header on the packet in preparation for
+// shoving it out the door.
+//
   AddHeader(packet, protocolNumber);
 
 //
-// This class simulates a point to point device.  In the case of a serial
-// link, this means that we're simulating something like a UART.
-//
-//
 // If there's a transmission in progress, we enque the packet for later
 // transmission; otherwise we send it now.
+//
   if (m_txMachineState == READY) 
     {
-// We still enqueue and dequeue it to hit the tracing hooks
+// 
+// Even if the transmitter is immediately available, we still enqueue and 
+// dequeue the packet to hit the tracing hooks.
+//
       m_queue->Enqueue (packet);
       packet = m_queue->Dequeue ();
       return TransmitStart (packet);
@@ -368,26 +424,29 @@
       return m_queue->Enqueue(packet);
     }
 }
-Ptr<Node> 
+
+  Ptr<Node> 
 PointToPointNetDevice::GetNode (void) const
 {
   return m_node;
 }
-void 
+
+  void 
 PointToPointNetDevice::SetNode (Ptr<Node> node)
 {
   m_node = node;
 }
-bool 
+
+  bool 
 PointToPointNetDevice::NeedsArp (void) const
 {
   return false;
 }
-void 
+
+  void 
 PointToPointNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
 {
   m_rxCallback = cb;
 }
 
-
 } // namespace ns3
--- a/src/devices/point-to-point/point-to-point-net-device.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Wed Jun 04 17:19:32 2008 -0400
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
- * Copyright (c) 2007 University of Washington
+ * Copyright (c) 2007, 2008 University of Washington
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,8 +14,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Craig Dowell <craigdo@ee.washington.edu>
  */
 
 #ifndef POINT_TO_POINT_NET_DEVICE_H
@@ -62,16 +60,16 @@
    * This is the constructor for the PointToPointNetDevice.  It takes as a
    * parameter a pointer to the Node to which this device is connected, 
    * as well as an optional DataRate object.
-   *
-   * @see PointToPointTopology::AddPointToPointLink ()
    */
   PointToPointNetDevice ();
+
   /**
    * Destroy a PointToPointNetDevice
    *
    * This is the destructor for the PointToPointNetDevice.
    */
   virtual ~PointToPointNetDevice ();
+
   /**
    * 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
@@ -80,48 +78,35 @@
    * @see Attach ()
    * @param bps the data rate at which this object operates
    */
-  void SetDataRate (const DataRate& bps);
+  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 (const Time& t);
+  void SetInterframeGap (Time t);
+
   /**
    * Attach the device to a channel.
    *
-   * The PointToPointTopology object creates a PointToPointChannel and two
-   * PointtoPointNetDevices.  In order to introduce these components to each
-   * other, the topology object calls Attach () on each PointToPointNetDevice.
-   * Inside this method, the Net Device calls out to the PointToPointChannel
-   * to introduce itself.
-   *
-   * @see PointToPointTopology::AddPointToPointLink ()
-   * @see SetDataRate ()
-   * @see SetInterframeGap ()
-   * @param ch a pointer to the channel to which this object is being attached.
+   * @param ch Ptr to the channel to which this object is being attached.
    */
   bool Attach (Ptr<PointToPointChannel> ch);
+
   /**
    * Attach a queue to the PointToPointNetDevice.
    *
-   * The PointToPointNetDevice "owns" a queue.  This queue is created by the
-   * PointToPointTopology object and implements a queueing method such as
-   * DropTail or RED.  The PointToPointNetDevice assumes ownership of this
-   * queue and must delete it when the device is destroyed.
+   * The PointToPointNetDevice "owns" a queue that implements a queueing 
+   * method such as DropTail or RED.  
    *
-   * @see PointToPointTopology::AddPointToPointLink ()
    * @see Queue
    * @see DropTailQueue
-   * @param queue a pointer to the queue for which object is assuming
-   *        ownership.
+   * @param queue Ptr to the new queue.
    */
   void SetQueue (Ptr<Queue> queue);
+
   /**
    * Attach a receive ErrorModel to the PointToPointNetDevice.
    *
@@ -129,9 +114,10 @@
    * the packet receive chain.
    *
    * @see ErrorModel
-   * @param em a pointer to the ErrorModel 
+   * @param em Ptr to the ErrorModel.
    */
   void SetReceiveErrorModel(Ptr<ErrorModel> em);
+
   /**
    * Receive a packet from a connected PointToPointChannel.
    *
@@ -141,46 +127,67 @@
    * arrived at the device.
    *
    * @see PointToPointChannel
-   * @param p a reference to the received packet
+   * @param p Ptr to the received packet.
    */
   void Receive (Ptr<Packet> p);
 
-  void SetAddress (Mac48Address self);
+  /**
+   * Assign a MAC address to this device.
+   *
+   * @see Mac48Address
+   * @param addr The new address.
+   */
+  void SetAddress (Mac48Address addr);
 
-  // inherited from NetDevice base class.
+//
+// Pure virtual methods inherited from NetDevice we must implement.
+//
   virtual void SetName(const std::string name);
   virtual std::string GetName(void) const;
+
   virtual void SetIfIndex(const uint32_t index);
   virtual uint32_t GetIfIndex(void) const;
+
   virtual Ptr<Channel> GetChannel (void) const;
   virtual Address GetAddress (void) const;
+
   virtual bool SetMtu (const uint16_t mtu);
   virtual uint16_t GetMtu (void) const;
+
   virtual bool IsLinkUp (void) const;
+
   virtual void SetLinkChangeCallback (Callback<void> callback);
+
   virtual bool IsBroadcast (void) const;
   virtual Address GetBroadcast (void) const;
+
   virtual bool IsMulticast (void) const;
   virtual Address GetMulticast (void) const;
   virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+
   virtual bool IsPointToPoint (void) const;
-  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+
+  virtual bool Send(Ptr<Packet> packet, const Address &dest, 
+    uint16_t protocolNumber);
+
   virtual Ptr<Node> GetNode (void) const;
   virtual void SetNode (Ptr<Node> node);
+
   virtual bool NeedsArp (void) const;
+
   virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
 private:
 
   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.
    *
-   * @see PointToPointTopology
-   * @returns a pointer to the queue.
+   * @returns Ptr to the queue.
    */
   Ptr<Queue> GetQueue(void) const; 
 
@@ -190,6 +197,7 @@
    * respect the protocol implemented by the agent.
    */
   void AddHeader(Ptr<Packet> p, uint16_t protocolNumber);
+
   /**
    * Removes, from a packet of data, all headers and trailers that
    * relate to the protocol implemented by the agent
@@ -197,6 +205,7 @@
    * protocol stack.
    */
   bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
+
   /**
    * Start Sending a Packet Down the Wire.
    *
@@ -213,14 +222,15 @@
    * @returns true if success, false on failure
    */
   bool TransmitStart (Ptr<Packet> p);
+
   /**
    * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
    *
    * The TransmitComplete method is used internally to finish the process
    * of sending a packet out on the channel.
-   *
    */
   void TransmitComplete(void);
+
   void NotifyLinkUp (void);
 
   /**
@@ -236,24 +246,28 @@
    * @see TxMachineState
    */
   TxMachineState m_txMachineState;
+
   /**
    * 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;
+
   /**
    * The PointToPointChannel to which this PointToPointNetDevice has been
    * attached.
    * @see class PointToPointChannel
    */
   Ptr<PointToPointChannel> m_channel;
+
   /**
    * The Queue which this PointToPointNetDevice uses as a packet source.
    * Management of this Queue has been delegated to the PointToPointNetDevice
@@ -262,20 +276,20 @@
    * @see class DropTailQueue
    */
   Ptr<Queue> m_queue;
+
   /**
    * The trace source for the packet reception events that the device can
    * fire.
    *
    * @see class CallBackTraceSource
-   * @see class TraceResolver
    */
   TracedCallback<Ptr<const Packet> > m_rxTrace;
+
   /**
    * The trace source for the packet drop events that the device can
    * fire.
    *
    * @see class CallBackTraceSource
-   * @see class TraceResolver
    */
   TracedCallback<Ptr<const Packet> > m_dropTrace;
 
--- a/src/devices/point-to-point/point-to-point.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/point-to-point.h	Wed Jun 04 17:19:32 2008 -0400
@@ -1,11 +1,45 @@
 /**
  * \ingroup devices
- * \defgroup PointToPoint Point-to-Point Models
+ * \defgroup PointToPoint Point-to-Point Model
+ *
+ * \section Point-to-Point Model
+ *
+ * The ns-3 point-to-point model is of a very simple point to point data link
+ * connecting exactly two ns3::PointToPointNetDevice devices over an
+ * ns3::PointToPointChannel.  This can be viewed as equivalent to a full
+ * duplex RS-232 or RS-422 link with null modem and no handshaking.
  *
- * \section Point-to-Point Models
+ * Data is encapsulated in the Point-to-Point Protocol (PPP -- RFC 1661),
+ * however the Link Control Protocol (LCP) and associated state machine is 
+ * not implemented.  The PPP link is assumed to be established and 
+ * authenticated at all times.
+ *
+ * Data is not framed, therefore Address and Control fields will not be found.
+ * Since the data is not framed, there is no need to provide Flag Sequence and
+ * Control Escape octets, nor is a Frame Check Sequence appended.  All that is
+ * required to implement non-framed PPP is to prepend the PPP protocol number
+ * for IP Version 4 which is the sixteen-bit number 0x21 (see
+ * http://www.iana.org/assignments/ppp-numbers).
  *
- * The set of Point-to-Point models provides an abstrated point-to-point link
- * model, that simulates transmission delay (finite data rate) and 
- * propagation delay, and can also optionally include an error model
- * (ns3::ErrorModel).
+ * The ns3::PointToPointNetDevice provides following Attributes:
+ *
+ * - Address:       The ns3::Mac48Address of the device (if desired);
+ * - DataRate:      The data rate of the device;
+ * - TxQueue:       The trasmit queue used by the device;
+ * - InterframeGap: The optional time to wait between "frames";
+ * - Rx:            A trace source for received packets;
+ * - Drop:          A trace source for dropped packets.
+ *
+ * The ns3::PointToPointNetDevice supports the assignment of a "receive error 
+ * model."  This is an ns3::ErrorModel object that is used to simulate data
+ * corruption on the link.
+ *
+ * The point to point net devices are connected via an 
+ * ns3::PointToPointChannel.  This channel models two wires transmitting bits
+ * at the data rate specified by the source net device.  There is no overhead
+ * beyond the eight bits per byte of the packet sent.  That is, we do not 
+ * model Flag Sequences, Frame Check Sequences nor do we "escape" any data.
+ *
+ * The ns3::PointToPointChannel does model a speed-of-light or transmission
+ * delay which can be set and get via the attribute "Delay."
  */
--- a/src/devices/point-to-point/ppp-header.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/point-to-point/ppp-header.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -55,7 +55,7 @@
 void 
 PppHeader::Print (std::ostream &os) const
 {
-  os << "Point-to-Point Protocol: IP (0x0021)" << std::endl;
+  os << "Point-to-Point Protocol: IP (0x0021)";
 }
 
   uint32_t
--- a/src/devices/wifi/adhoc-wifi-mac.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/adhoc-wifi-mac.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -137,9 +137,7 @@
 }
 void 
 AdhocWifiMac::SetLinkDownCallback (Callback<void> linkDown)
-{
-  //XXX
-}
+{}
 Mac48Address 
 AdhocWifiMac::GetAddress (void) const
 {
--- a/src/devices/wifi/constant-rate-wifi-manager.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/constant-rate-wifi-manager.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -77,11 +77,11 @@
   static TypeId tid = TypeId ("ns3::ConstantRateWifiManager")
     .SetParent<WifiRemoteStationManager> ()
     .AddConstructor<ConstantRateWifiManager> ()
-    .AddAttribute ("DataMode", "XXX",
+    .AddAttribute ("DataMode", "The transmission mode to use for every data packet transmission",
                    StringValue ("wifia-6mbs"),
                    MakeWifiModeAccessor (&ConstantRateWifiManager::m_dataMode),
                    MakeWifiModeChecker ())
-    .AddAttribute ("ControlMode", "XXX",
+    .AddAttribute ("ControlMode", "The transmission mode to use for every control packet transmission.",
                    StringValue ("wifia-6mbs"),
                    MakeWifiModeAccessor (&ConstantRateWifiManager::m_ctlMode),
                    MakeWifiModeChecker ())
--- a/src/devices/wifi/dca-txop.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/dca-txop.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -99,17 +99,17 @@
   static TypeId tid = TypeId ("DcaTxop")
     .SetParent<Object> ()
     .AddConstructor<DcaTxop> ()
-    .AddAttribute ("MinCw", "XXX",
+    .AddAttribute ("MinCw", "The minimum value of the contention window.",
                    UintegerValue (15),
                    MakeUintegerAccessor (&DcaTxop::SetMinCw,
                                          &DcaTxop::GetMinCw),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("MaxCw", "XXX",
+    .AddAttribute ("MaxCw", "The maximum value of the contention window.",
                    UintegerValue (1023),
                    MakeUintegerAccessor (&DcaTxop::SetMaxCw,
                                          &DcaTxop::GetMaxCw),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("Aifsn", "XXX",
+    .AddAttribute ("Aifsn", "The AIFSN: the default value conforms to simple DCA.",
                    UintegerValue (2),
                    MakeUintegerAccessor (&DcaTxop::SetAifsn,
                                          &DcaTxop::GetAifsn),
@@ -139,6 +139,9 @@
 DcaTxop::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
+  m_queue = 0;
+  m_low = 0;
+  m_stationManager = 0;
   delete m_transmissionListener;
   delete m_dcf;
   delete m_rng;
@@ -147,9 +150,6 @@
   m_dcf = 0;
   m_rng = 0;
   m_txMiddle = 0;
-  m_queue = 0;
-  m_low = 0;
-  m_stationManager = 0;
 }
 
 void
--- a/src/devices/wifi/mac-low.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/mac-low.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -40,14 +40,14 @@
 class SnrTag : public Tag
 {
 public:
-  SnrTag ();
-  SnrTag (const SnrTag &o);
-  ~SnrTag ();
-  static uint32_t GetUid (void);
-  void Print (std::ostream &os) const;
-  uint32_t GetSerializedSize (void) const;
-  void Serialize (Buffer::Iterator i) const;
-  uint32_t Deserialize (Buffer::Iterator i);
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
 
   void Set (double snr);
   double Get (void) const;
@@ -55,40 +55,44 @@
   double m_snr;
 };
 
-SnrTag::SnrTag ()
-  : m_snr (0.0)
-{}
-SnrTag::SnrTag (const SnrTag &o)
-  : m_snr (o.m_snr)
-{}
-SnrTag::~SnrTag ()
-{}
+TypeId 
+SnrTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SnrTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SnrTag> ()
+    .AddAttribute ("Snr", "The snr of the last packet received",
+                   DoubleValue (0.0),
+                   MakeDoubleAccessor (&SnrTag::Get),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+}
+TypeId 
+SnrTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
 uint32_t 
-SnrTag::GetUid (void)
+SnrTag::GetSerializedSize (void) const
+{
+  return sizeof (double);
+}
+void 
+SnrTag::Serialize (TagBuffer i) const
 {
-  static uint32_t uid = AllocateUid<SnrTag> ("SnrTag.ns3.inria.fr");
-  return uid;
+  i.WriteDouble (m_snr);
+}
+void 
+SnrTag::Deserialize (TagBuffer i)
+{
+  m_snr = i.ReadDouble ();
 }
 void 
 SnrTag::Print (std::ostream &os) const
 {
-  os << "snr="<<m_snr;
-}
-uint32_t 
-SnrTag::GetSerializedSize (void) const
-{
-  return 0;
-}
-void 
-SnrTag::Serialize (Buffer::Iterator i) const
-{
-  // would need to serialize double to platform-independent format.
-}
-uint32_t 
-SnrTag::Deserialize (Buffer::Iterator i)
-{
-  // would need to deserialize double from platform-independent format.
-  return 0;
+  os << "Snr=" << m_snr;
 }
 void 
 SnrTag::Set (double snr)
@@ -472,7 +476,7 @@
     {
       MY_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
-      packet->PeekTag (tag);
+      packet->FindFirstMatchingTag (tag);
       WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportRxOk (rxSnr, txMode);
       station->ReportRtsOk (rxSnr, txMode, tag.Get ());
@@ -495,7 +499,7 @@
     {
       MY_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
       SnrTag tag;
-      packet->PeekTag (tag);
+      packet->FindFirstMatchingTag (tag);
       WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
       station->ReportRxOk (rxSnr, txMode);
       station->ReportDataOk (rxSnr, txMode, tag.Get ());
--- a/src/devices/wifi/nqap-wifi-mac.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/nqap-wifi-mac.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -44,7 +44,7 @@
     .SetParent<WifiMac> ()
     .AddConstructor<NqapWifiMac> ()
     .AddAttribute ("BeaconInterval", "Delay between two beacons",
-                   TimeValue (Seconds (1.0)),
+                   TimeValue (Seconds (0.1)),
                    MakeTimeAccessor (&NqapWifiMac::m_beaconInterval),
                    MakeTimeChecker ())
     .AddAttribute ("BeaconGeneration", "Whether or not beacons are generated.",
--- a/src/devices/wifi/nqsta-wifi-mac.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/nqsta-wifi-mac.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -38,18 +38,18 @@
 
 /*
  * The state machine for this NQSTA is:
- --------------            -----------
+ --------------                                          -----------
  | Associated |   <--------------------      ------->    | Refused |
- --------------      \    /      -----------
-    \           \  /
+ --------------                        \    /            -----------
+    \                                   \  /
      \    -----------------     -----------------------------
       \-> | Beacon Missed | --> | Wait Association Response |
-    -----------------     -----------------------------
-    \           ^
-     \          |
-      \    -----------------------
-       \-> | Wait Probe Response |
-           -----------------------
+          -----------------     -----------------------------
+	        \                       ^
+		 \                      |
+		  \    -----------------------
+	           \-> | Wait Probe Response |
+		       -----------------------
  */
 
 namespace ns3 {
@@ -62,11 +62,11 @@
   static TypeId tid = TypeId ("ns3::NqstaWifiMac")
     .SetParent<WifiMac> ()
     .AddConstructor<NqstaWifiMac> ()
-    .AddAttribute ("ProbeRequestTimeout", "XXX",
-                   TimeValue (Seconds (0.5)),
+    .AddAttribute ("ProbeRequestTimeout", "The interval between two consecutive probe request attempts.",
+                   TimeValue (Seconds (0.05)),
                    MakeTimeAccessor (&NqstaWifiMac::m_probeRequestTimeout),
                    MakeTimeChecker ())
-    .AddAttribute ("AssocRequestTimeout", "XXX",
+    .AddAttribute ("AssocRequestTimeout", "The interval between two consecutive assoc request attempts.",
                    TimeValue (Seconds (0.5)),
                    MakeTimeAccessor (&NqstaWifiMac::m_assocRequestTimeout),
                    MakeTimeChecker ())
@@ -76,7 +76,7 @@
                    UintegerValue (10),
                    MakeUintegerAccessor (&NqstaWifiMac::m_maxMissedBeacons),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("ActiveProbing", "XXX",
+    .AddAttribute ("ActiveProbing", "If true, we send probe requests. If false, we don't.",
                    BooleanValue (false),
                    MakeBooleanAccessor (&NqstaWifiMac::SetActiveProbing),
                    MakeBooleanChecker ())
--- a/src/devices/wifi/onoe-wifi-manager.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/onoe-wifi-manager.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -40,7 +40,7 @@
                    TimeValue (Seconds (1.0)),
                    MakeTimeAccessor (&OnoeWifiManager::m_updatePeriod),
                    MakeTimeChecker ())
-    .AddAttribute ("RaiseThreshold", "XXX",
+    .AddAttribute ("RaiseThreshold", "Attempt to raise the rate if we hit that threshold",
                    UintegerValue (10),
                    MakeUintegerAccessor (&OnoeWifiManager::m_raiseThreshold),
                    MakeUintegerChecker<uint32_t> ())
--- a/src/devices/wifi/propagation-loss-model.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/propagation-loss-model.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -55,7 +55,7 @@
   static TypeId tid = TypeId ("ns3::RandomPropagationLossModel")
     .SetParent<PropagationLossModel> ()
     .AddConstructor<RandomPropagationLossModel> ()
-    .AddAttribute ("Variable", "XXX",
+    .AddAttribute ("Variable", "The random variable used to pick a loss everytime GetLoss is invoked.",
                    RandomVariableValue (ConstantVariable (1.0)),
                    MakeRandomVariableAccessor (&RandomPropagationLossModel::m_variable),
                    MakeRandomVariableChecker ())
--- a/src/devices/wifi/ssid.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/ssid.h	Wed Jun 04 17:19:32 2008 -0400
@@ -49,7 +49,6 @@
   Buffer::Iterator Serialize (Buffer::Iterator i) const;
   Buffer::Iterator Deserialize (Buffer::Iterator i);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ssid);
 private:
   uint8_t m_ssid[33];
   uint8_t m_length;
@@ -63,7 +62,7 @@
  * \brief hold objects of type ns3::Ssid
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Ssid);
+ATTRIBUTE_HELPER_HEADER (Ssid);
 
 } // namespace ns3
 
--- a/src/devices/wifi/wifi-channel.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-channel.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -38,11 +38,11 @@
   static TypeId tid = TypeId ("ns3::WifiChannel")
     .SetParent<Channel> ()
     .AddConstructor<WifiChannel> ()
-    .AddAttribute ("PropagationLossModel", "XXX",
+    .AddAttribute ("PropagationLossModel", "A pointer to the propagation loss model attached to this channel.",
                    PointerValue (),
                    MakePointerAccessor (&WifiChannel::m_loss),
                    MakePointerChecker<PropagationLossModel> ())
-    .AddAttribute ("PropagationDelayModel", "XXX",
+    .AddAttribute ("PropagationDelayModel", "A pointer to the propagation delay model attached to this channel.",
                    PointerValue (),
                    MakePointerAccessor (&WifiChannel::m_delay),
                    MakePointerChecker<PropagationDelayModel> ())
--- a/src/devices/wifi/wifi-mac-header.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-mac-header.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -40,7 +40,9 @@
 };
 
 WifiMacHeader::WifiMacHeader ()
-  : m_ctrlMoreData (0)
+  : m_ctrlMoreData (0),
+    m_ctrlWep (0),
+    m_ctrlOrder (1)
 {}
 WifiMacHeader::~WifiMacHeader ()
 {}
--- a/src/devices/wifi/wifi-mac.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-mac.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -73,42 +73,43 @@
 {
   static TypeId tid = TypeId ("ns3::WifiMac")
     .SetParent<Object> ()
-    .AddAttribute ("CtsTimeout", "XXX",
+    .AddAttribute ("CtsTimeout", "When this timeout expires, the RTS/CTS handshake has failed.",
                    TimeValue (GetDefaultCtsAckTimeout ()),
                    MakeTimeAccessor (&WifiMac::m_ctsTimeout),
                    MakeTimeChecker ())
-    .AddAttribute ("AckTimeout", "XXX",
+    .AddAttribute ("AckTimeout", "When this timeout expires, the DATA/ACK handshake has failed.",
                    TimeValue (GetDefaultCtsAckTimeout ()),
                    MakeTimeAccessor (&WifiMac::m_ackTimeout),
                    MakeTimeChecker ())
-    .AddAttribute ("Sifs", "XXX",
+    .AddAttribute ("Sifs", "The value of the SIFS constant.",
                    TimeValue (GetDefaultSifs ()),
                    MakeTimeAccessor (&WifiMac::SetSifs,
 				     &WifiMac::GetSifs),
                    MakeTimeChecker ())
-    .AddAttribute ("EifsNoDifs", "XXX",
+    .AddAttribute ("EifsNoDifs", "The value of EIFS-DIFS",
 		   TimeValue (GetDefaultEifsNoDifs ()),
 		   MakeTimeAccessor (&WifiMac::SetEifsNoDifs,
 				     &WifiMac::GetEifsNoDifs),
 		   MakeTimeChecker ())
-    .AddAttribute ("Slot", "XXX",
+    .AddAttribute ("Slot", "The duration of a Slot.",
                    TimeValue (GetDefaultSlot ()),
                    MakeTimeAccessor (&WifiMac::SetSlot,
 				     &WifiMac::GetSlot),
                    MakeTimeChecker ())
-    .AddAttribute ("Pifs", "XXX",
+    .AddAttribute ("Pifs", "The value of the PIFS constant.",
                    TimeValue (GetDefaultSifs () + GetDefaultSlot ()),
                    MakeTimeAccessor (&WifiMac::m_pifs),
                    MakeTimeChecker ())
-    .AddAttribute ("MaxPropagationDelay", "XXX",
+    .AddAttribute ("MaxPropagationDelay", "The maximum propagation delay. Unused for now.",
                    TimeValue (GetDefaultMaxPropagationDelay ()),
                    MakeTimeAccessor (&WifiMac::m_maxPropagationDelay),
                    MakeTimeChecker ())
-    .AddAttribute ("MaxMsduSize", "XXX",
+    .AddAttribute ("MaxMsduSize", "The maximum size of an MSDU accepted by the MAC layer."
+                   "This value conforms to the specification.",
 		   UintegerValue (2304),
 		   MakeUintegerAccessor (&WifiMac::m_maxMsduSize),
 		   MakeUintegerChecker<uint16_t> (1,2304))
-    .AddAttribute ("Ssid", "XXX",
+    .AddAttribute ("Ssid", "The ssid we want to belong to.",
 		   SsidValue (Ssid ("default")),
 		   MakeSsidAccessor (&WifiMac::GetSsid,
 				     &WifiMac::SetSsid),
--- a/src/devices/wifi/wifi-mac.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-mac.h	Wed Jun 04 17:19:32 2008 -0400
@@ -70,13 +70,9 @@
    */
   void SetAckTimeout (Time ackTimeout);
   /**
-   * \param msduLifetime
+   * \param delay the max propagation delay.
    *
-   * XXX: I cannot remmeber what this is used for.
-   */
-  void SetMsduLifetime (Time msduLifetime);
-  /**
-   * XXX: I cannot remember what this is used for.
+   * Unused for now.
    */
   void SetMaxPropagationDelay (Time delay);
 
@@ -105,11 +101,11 @@
    */
   Time GetAckTimeout (void) const;
   /**
-   * XXX: I cannot remember what this is used for.
+   * Unused for now.
    */
   Time GetMsduLifetime (void) const;
   /**
-   * XXX: I cannot remember what this is used for.
+   * Unused for now.
    */
   Time GetMaxPropagationDelay (void) const;
   /**
--- a/src/devices/wifi/wifi-mode.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-mode.h	Wed Jun 04 17:19:32 2008 -0400
@@ -107,7 +107,6 @@
    */
   WifiMode ();
 
-  ATTRIBUTE_HELPER_HEADER_1 (WifiMode);
 private:
   friend class WifiModeFactory;
   WifiMode (uint32_t uid);
@@ -123,7 +122,7 @@
  * \brief hold objects of type ns3::WifiMode
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (WifiMode);
+ATTRIBUTE_HELPER_HEADER (WifiMode);
 
 /**
  * \brief create WifiMode class instances and keep track of them.
--- a/src/devices/wifi/wifi-phy.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-phy.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -227,7 +227,8 @@
                    MakeDoubleAccessor (&WifiPhy::SetRxNoise,
                                        &WifiPhy::GetRxNoise),
                    MakeDoubleChecker<double> ())
-    .AddAttribute ("Standard", "XXX",
+    .AddAttribute ("Standard", "The standard chosen configures a set of transmission modes"
+                   " and some PHY-specific constants.",
                    EnumValue (WIFI_PHY_STANDARD_80211a),
                    MakeEnumAccessor (&WifiPhy::SetStandard),
                    MakeEnumChecker (WIFI_PHY_STANDARD_80211a, "802.11a",
@@ -712,7 +713,9 @@
     return "SYNC";
     break;
   default:
-    return "XXX";
+    NS_ASSERT (false);
+    // quiet compiler
+    return "INVALID";
     break;
   }
 }
--- a/src/devices/wifi/wifi-remote-station-manager.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-remote-station-manager.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -126,23 +126,32 @@
 {
   static TypeId tid = TypeId ("ns3::WifiRemoteStationManager")
     .SetParent<Object> ()
-    .AddAttribute ("IsLowLatency", "XXX",
+    .AddAttribute ("IsLowLatency", "If true, we attempt to modelize a so-called low-latency device: a device"
+                   " where decisions about tx parameters can be made on a per-packet basis and feedback about the"
+                   " transmission of each packet is obtained before sending the next. Otherwise, we modelize a "
+                   " high-latency device, that is a device where we cannot update our decision about tx parameters"
+                   " after every packet transmission.",
                    BooleanValue (true),
                    MakeBooleanAccessor (&WifiRemoteStationManager::m_isLowLatency),
                    MakeBooleanChecker ())
-    .AddAttribute ("MaxSsrc", "XXX",
+    .AddAttribute ("MaxSsrc", "The maximum number of retransmission attempts for an RTS. This value"
+                   " will not have any effect on some rate control algorithms.",
                    UintegerValue (7),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSsrc),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("MaxSlrc", "XXX",
+    .AddAttribute ("MaxSlrc", "The maximum number of retransmission attempts for a DATA packet. This value"
+                   " will not have any effect on some rate control algorithms.",
                    UintegerValue (7),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_maxSlrc),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("RtsCtsThreshold", "XXX",
+    .AddAttribute ("RtsCtsThreshold", "If a data packet is bigger than this value, we use an RTS/CTS handshake"
+                   " before sending the data. This value will not have any effect on some rate control algorithms.",
                    UintegerValue (1500),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_rtsCtsThreshold),
                    MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("FragmentationThreshold", "XXX",
+    .AddAttribute ("FragmentationThreshold", "If a data packet is bigger than this value, we fragment it such that"
+                   " the size of the fragments are equal or smaller than this value. This value will not have any effect"
+                   " on some rate control algorithms.",
                    UintegerValue (1500),
                    MakeUintegerAccessor (&WifiRemoteStationManager::m_fragmentationThreshold),
                    MakeUintegerChecker<uint32_t> ())
@@ -314,11 +323,12 @@
   WifiMode GetRtsMode (void) const;
   WifiMode GetDataMode (void) const;
 
-  static uint32_t GetUid (void);
-  void Print (std::ostream &os) const;
-  void Serialize (ns3::Buffer::Iterator start) const;
-  uint32_t Deserialize (ns3::Buffer::Iterator start);
-  uint32_t GetSerializedSize (void) const;
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
 private:
   WifiMode m_rtsMode;
   WifiMode m_dataMode;
@@ -340,30 +350,51 @@
 {
   return m_dataMode;
 }
-
+TypeId 
+TxModeTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::TxModeTag")
+    .SetParent<Tag> ()
+    .AddConstructor<TxModeTag> ()
+    .AddAttribute ("RtsTxMode", 
+                   "Tx mode of rts to use later",
+                   EmptyAttributeValue (),
+                   MakeWifiModeAccessor (&TxModeTag::GetRtsMode),
+                   MakeWifiModeChecker ())
+    .AddAttribute ("DataTxMode", 
+                   "Tx mode of data to use later",
+                   EmptyAttributeValue (),
+                   MakeWifiModeAccessor (&TxModeTag::GetDataMode),
+                   MakeWifiModeChecker ())
+    ;
+  return tid;
+}
+TypeId 
+TxModeTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
 uint32_t 
-TxModeTag::GetUid (void)
+TxModeTag::GetSerializedSize (void) const
+{
+  return sizeof (WifiMode) * 2;
+}
+void 
+TxModeTag::Serialize (TagBuffer i) const
 {
-  static uint32_t uid = Tag::AllocateUid<TxModeTag> ("ns3.wifi.TxModeTag");
-  return uid;
+  i.Write ((uint8_t *)&m_rtsMode, sizeof (WifiMode));
+  i.Write ((uint8_t *)&m_dataMode, sizeof (WifiMode));
+}
+void 
+TxModeTag::Deserialize (TagBuffer i)
+{
+  i.Read ((uint8_t *)&m_rtsMode, sizeof (WifiMode));
+  i.Read ((uint8_t *)&m_dataMode, sizeof (WifiMode));
 }
 void 
 TxModeTag::Print (std::ostream &os) const
 {
-  os << "rts="<<m_rtsMode<<" data="<<m_dataMode;
-}
-void 
-TxModeTag::Serialize (ns3::Buffer::Iterator start) const
-{}
-uint32_t 
-TxModeTag::Deserialize (ns3::Buffer::Iterator start)
-{
-  return 0;
-}
-uint32_t 
-TxModeTag::GetSerializedSize (void) const
-{
-  return 0;
+  os << "Rts=" << m_rtsMode << ", Data=" << m_dataMode;
 }
 
 } // namespace ns3
@@ -380,9 +411,9 @@
 {
   static TypeId tid = TypeId ("ns3::WifiRemoteStation")
     .SetParent<Object> ()
-    .AddTraceSource ("Ssrc", "XXX",
+    .AddTraceSource ("Ssrc", "The value of the ssrc counter: indicates the number of retransmissions of RTS.",
                      MakeTraceSourceAccessor (&WifiRemoteStation::m_ssrc))
-    .AddTraceSource ("Slrc", "XXX",
+    .AddTraceSource ("Slrc", "The value of the slrc counter: indicates the number of retransmissions of DATA.",
                      MakeTraceSourceAccessor (&WifiRemoteStation::m_slrc))
     ;
   return tid;
@@ -546,7 +577,7 @@
     }
   TxModeTag tag;
   bool found;
-  found = packet->PeekTag (tag);
+  found = packet->FindFirstMatchingTag (tag);
   NS_ASSERT (found);
   return tag.GetDataMode ();
 }
@@ -559,7 +590,7 @@
     }
   TxModeTag tag;
   bool found;
-  found = packet->PeekTag (tag);
+  found = packet->FindFirstMatchingTag (tag);
   NS_ASSERT (found);
   return tag.GetRtsMode ();
 }
--- a/src/devices/wifi/wifi-remote-station-manager.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-remote-station-manager.h	Wed Jun 04 17:19:32 2008 -0400
@@ -35,12 +35,9 @@
 class WifiPhy;
 
 /**
- * \brief hold per-remote-station state.
+ * \brief hold a list of per-remote-station state.
  *
- * The state in this class is used to keep track
- * of association status if we are in an infrastructure
- * network and to perform the selection of tx parameters
- * on a per-packet basis.
+ * \sa ns3::WifiRemoteStation.
  */
 class WifiRemoteStationManager : public Object
 {
@@ -106,6 +103,14 @@
 
 namespace ns3 {
 
+/**
+ * \brief hold per-remote-station state.
+ *
+ * The state in this class is used to keep track
+ * of association status if we are in an infrastructure
+ * network and to perform the selection of tx parameters
+ * on a per-packet basis.
+ */
 class WifiRemoteStation {
 public:
   
@@ -114,14 +119,18 @@
   WifiRemoteStation ();
   virtual ~WifiRemoteStation ();
 
-  // Invoked in an AP upon disassociation of a
-  // specific STA.
+  /**
+   * Invoked in an AP upon disassociation of a
+   * specific STA.
+   */
   void Reset (void);
-  // Invoked in a STA or AP to store the set of 
-  // modes supported by a destination which is
-  // also supported locally.
-  // The set of supported modes includes
-  // the BSSBasicRateSet.
+  /**
+   * Invoked in a STA or AP to store the set of 
+   * modes supported by a destination which is
+   * also supported locally.
+   * The set of supported modes includes
+   * the BSSBasicRateSet.
+   */
   void AddSupportedMode (WifiMode mode);
 
   bool IsBrandNew (void) const;
@@ -132,30 +141,120 @@
   void RecordGotAssocTxFailed (void);
   void RecordDisassociated (void);
 
+  /**
+   * \param packet the packet to queue
+   * \param fullPacketSize the size of the packet after its 802.11 MAC header has been added.
+   *
+   * This method is typically invoked just before queuing a packet for transmission.
+   * It is a no-op unless the IsLowLatency attribute of the attached ns3::WifiRemoteStationManager
+   * is set to false, in which case, the tx parameters of the packet are calculated and stored in
+   * the packet as a tag. These tx parameters are later retrieved from GetDadaMode and GetRtsMode.
+   */
   void PrepareForQueue (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  /**
+   * \param packet the packet to send
+   * \param fullPacketSize the size of the packet after its 802.11 MAC header has been added.
+   * \returns the transmission mode to use to send this packet
+   */
   WifiMode GetDataMode (Ptr<const Packet> packet, uint32_t fullPacketSize);
+  /**
+   * \param packet the packet to send
+   * \returns the transmission mode to use to send the RTS prior to the
+   *          transmission of the data packet itself.
+   */
   WifiMode GetRtsMode (Ptr<const Packet> packet);
-  // transmission-related methods
+  /**
+   * Should be invoked whenever the RtsTimeout associated to a transmission
+   * attempt expires.
+   */
   void ReportRtsFailed (void);
+  /**
+   * Should be invoked whenever the AckTimeout associated to a transmission
+   * attempt expires.
+   */
   void ReportDataFailed (void);
+  /**
+   * Should be invoked whenever we receive the Cts associated to an RTS 
+   * we just sent.
+   */
   void ReportRtsOk (double ctsSnr, WifiMode ctsMode, double rtsSnr);
+  /**
+   * Should be invoked whenever we receive the Ack associated to a data packet
+   * we just sent.
+   */
   void ReportDataOk (double ackSnr, WifiMode ackMode, double dataSnr);
+  /**
+   * Should be invoked after calling ReportRtsFailed if 
+   * NeedRtsRetransmission returns false
+   */
   void ReportFinalRtsFailed (void);
+  /**
+   * Should be invoked after calling ReportDataFailed if 
+   * NeedDataRetransmission returns false
+   */
   void ReportFinalDataFailed (void);
 
-  // reception-related method
+  /**
+   * \param rxSnr the snr of the packet received
+   * \param txMode the transmission mode used for the packet received.
+   *
+   * Should be invoked whenever a packet is successfully received.
+   */
   void ReportRxOk (double rxSnr, WifiMode txMode);
 
+  /**
+   * \param packet the packet to send
+   * \returns true if we want to use an RTS/CTS handshake for this
+   *          packet before sending it, false otherwise.
+   */
   virtual bool NeedRts (Ptr<const Packet> packet);
+  /**
+   * \param packet the packet to send
+   * \returns true if we want to restart a failed RTS/CTS 
+   *          handshake, false otherwise.
+   */
   virtual bool NeedRtsRetransmission (Ptr<const Packet> packet);
+  /**
+   * \param packet the packet to send
+   * \returns true if we want to resend a packet 
+   *          after a failed transmission attempt, false otherwise.
+   */
   virtual bool NeedDataRetransmission (Ptr<const Packet> packet);
 
+  /**
+   * \param packet the packet to send
+   * \returns true if this packet should be fragmented, false otherwise.
+   */
   virtual bool NeedFragmentation (Ptr<const Packet> packet);
+  /**
+   * \param packet the packet to send
+   * \returns the number of fragments which should be used for this packet.
+   */
   virtual uint32_t GetNFragments (Ptr<const Packet> packet);
+  /**
+   * \param packet the packet to send
+   * \param fragmentNumber the fragment index of the next fragment to send (starts at zero).
+   * \returns the size of the corresponding fragment.
+   */
   virtual uint32_t GetFragmentSize (Ptr<const Packet> packet, uint32_t fragmentNumber);
+  /**
+   * \param packet the packet to send
+   * \param fragmentNumber the fragment index of the next fragment to send (starts at zero).
+   * \returns true if this is the last fragment, false otherwise.
+   */
   virtual bool IsLastFragment (Ptr<const Packet> packet, uint32_t fragmentNumber);
 
+  /**
+   * \param rtsMode the transmission mode used to send an RTS we just received
+   * \returns the transmission mode to use for the CTS to complete the RTS/CTS
+   *          handshake.
+   */
   WifiMode GetCtsMode (WifiMode rtsMode);
+  /**
+   * \param dataMode the transmission mode used to send an ACK we just received
+   * \returns the transmission mode to use for the ACK to complete the data/ACK
+   *          handshake.
+   */
   WifiMode GetAckMode (WifiMode dataMode);
 
 private:
--- a/src/devices/wifi/wifi-test.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/devices/wifi/wifi-test.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -81,7 +81,7 @@
   Simulator::Run ();
   Simulator::Destroy ();
 
-  Simulator::StopAt (Seconds (10.0));
+  Simulator::Stop (Seconds (10.0));
 }
 
 bool
--- a/src/helper/ipv4-address-helper.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/ipv4-address-helper.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -54,9 +54,9 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  m_network = network.GetHostOrder ();
-  m_mask = mask.GetHostOrder ();
-  m_base = m_address = address.GetHostOrder ();
+  m_network = network.Get ();
+  m_mask = mask.Get ();
+  m_base = m_address = address.Get ();
 
 //
 // Some quick reasonableness testing.
--- a/src/helper/mobility-helper.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/mobility-helper.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -19,7 +19,6 @@
  */
 #include "ns3/mobility-helper.h"
 #include "ns3/mobility-model.h"
-#include "ns3/mobility-model-notifier.h"
 #include "ns3/position-allocator.h"
 #include "ns3/hierarchical-mobility-model.h"
 #include "ns3/log.h"
@@ -30,7 +29,6 @@
 NS_LOG_COMPONENT_DEFINE ("MobilityHelper");
 
 MobilityHelper::MobilityHelper ()
-  : m_notifierEnabled (false)
 {
   m_position = CreateObject<RandomRectanglePositionAllocator> 
     ("X", RandomVariableValue (ConstantVariable (0.0)),
@@ -40,16 +38,6 @@
 MobilityHelper::~MobilityHelper ()
 {}
 void 
-MobilityHelper::EnableNotifier (void)
-{
-  m_notifierEnabled = true;
-}
-void 
-MobilityHelper::DisableNotifier (void)
-{
-  m_notifierEnabled = false;
-}
-void 
 MobilityHelper::SetPositionAllocator (Ptr<PositionAllocator> allocator)
 {
   m_position = allocator;
@@ -156,15 +144,6 @@
 	}
       Vector position = m_position->GetNext ();
       model->SetPosition (position);
-      if (m_notifierEnabled)
-	{
-	  Ptr<MobilityModelNotifier> notifier = 
-	    object->GetObject<MobilityModelNotifier> ();
-	  if (notifier == 0)
-	    {
-	      object->AggregateObject (CreateObject<MobilityModelNotifier> ());
-	    }
-	}
     }
 }
 
--- a/src/helper/mobility-helper.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/mobility-helper.h	Wed Jun 04 17:19:32 2008 -0400
@@ -43,20 +43,6 @@
   ~MobilityHelper ();
 
   /**
-   * After this method is called, every call to MobilityHelper::Install
-   * will also attach to the new ns3::MobilityModel an ns3::MobilityModelNotifier
-   * which can be used to listen to CourseChange events.
-   */
-  void EnableNotifier (void);
-  /**
-   * After this method is called, no ns3::MobilityModelNotifier object will
-   * be associated to any new ns3::MobilityModel created by MobilityHelper::Install.
-   * This will make it impossible to listen to "CourseChange" events from these
-   * new ns3::MobilityModel instances.
-   */
-  void DisableNotifier (void);
-
-  /**
    * \param allocator allocate initial node positions
    *
    * Set the position allocator which will be used to allocate
@@ -169,9 +155,6 @@
    * subclass (the type of which was set with MobilityHelper::SetMobilityModel), 
    * aggregates it to the mode, and sets an initial position based on the current 
    * position allocator (set through MobilityHelper::SetPositionAllocator). 
-   * Optionally, this method will also create and aggregate a
-   * ns3::MobilityModelNotifier to generate 'CourseChange' events based on the 
-   * boolean flag set by MobilityHelper::EnableNotifierAll and MobilityHelper::DisableNotifier.
    */
   void Install (NodeContainer container);
 
@@ -183,7 +166,6 @@
 private:
 
   std::vector<Ptr<MobilityModel> > m_mobilityStack;
-  bool m_notifierEnabled;
   ObjectFactory m_mobility;
   Ptr<PositionAllocator> m_position;
 };
--- a/src/helper/ns2-mobility-helper.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/ns2-mobility-helper.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -24,7 +24,6 @@
 #include "ns3/node-list.h"
 #include "ns3/node.h"
 #include "ns3/static-speed-mobility-model.h"
-#include "ns3/mobility-model-notifier.h"
 #include "ns2-mobility-helper.h"
 
 NS_LOG_COMPONENT_DEFINE ("Ns2MobilityHelper");
@@ -36,17 +35,6 @@
   : m_filename (filename)
 {}
 
-void 
-Ns2MobilityHelper::EnableNotifier (void)
-{
-  m_notifierEnabled = true;
-}
-void 
-Ns2MobilityHelper::DisableNotifier (void)
-{
-  m_notifierEnabled = false;
-}
-
 
 
 Ptr<StaticSpeedMobilityModel>
@@ -67,12 +55,6 @@
       model = CreateObject<StaticSpeedMobilityModel> ();
       object->AggregateObject (model);
     }
-  Ptr<MobilityModelNotifier> notifier = object->GetObject<MobilityModelNotifier> ();
-  if (notifier == 0)
-    {
-      notifier = CreateObject<MobilityModelNotifier> ();
-      object->AggregateObject (notifier);
-    }
   return model;
 }
 
--- a/src/helper/ns2-mobility-helper.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/ns2-mobility-helper.h	Wed Jun 04 17:19:32 2008 -0400
@@ -42,9 +42,6 @@
    */
   Ns2MobilityHelper (std::string filename);
 
-  void EnableNotifier (void);
-  void DisableNotifier (void);
-
   /**
    * Read the ns2 trace file and configure the movement
    * patterns of all nodes contained in the global ns3::NodeList
@@ -77,7 +74,6 @@
   Ptr<StaticSpeedMobilityModel> GetMobilityModel (std::string idString, const ObjectStore &store) const;
   double ReadDouble (std::string valueString) const;
   std::string m_filename;
-  bool m_notifierEnabled;
 };
 
 } // namespace ns3
--- a/src/helper/wifi-helper.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/helper/wifi-helper.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -156,6 +156,7 @@
   oss.str ("");
   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/Tx";
   Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapPhyTxEvent, pcap));
+  oss.str ("");
   oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/RxOk";
   Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&PcapPhyRxEvent, pcap));
 }
--- a/src/internet-node/arp-cache.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-cache.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -20,24 +20,73 @@
 #include "ns3/assert.h"
 #include "ns3/packet.h"
 #include "ns3/simulator.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
 
 #include "arp-cache.h"
 #include "arp-header.h"
 #include "ipv4-interface.h"
 
+NS_LOG_COMPONENT_DEFINE ("ArpCache");
+
 namespace ns3 {
 
-ArpCache::ArpCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
-  : m_device (device), 
-    m_interface (interface),
-    m_aliveTimeout (Seconds (120)),
-    m_deadTimeout (Seconds (100)),
-    m_waitReplyTimeout (Seconds (1))
-{}
+TypeId 
+ArpCache::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::ArpCache")
+    .SetParent<Object> ()
+    .AddAttribute ("AliveTimeout",
+                   "When this timeout expires, the matching cache entry needs refreshing",
+                   TimeValue (Seconds (120)),
+                   MakeTimeAccessor (&ArpCache::m_aliveTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("DeadTimeout",
+                   "When this timeout expires, a new attempt to resolve the matching entry is made",
+                   TimeValue (Seconds (100)),
+                   MakeTimeAccessor (&ArpCache::m_deadTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("WaitReplyTimeout",
+                   "When this timeout expires, the matching cache entry is marked dead",
+                   TimeValue (Seconds (1)),
+                   MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("PendingQueueSize",
+                   "The size of the queue for packets pending an arp reply.",
+                   UintegerValue (3),
+                   MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+ArpCache::ArpCache ()
+  : m_device (0), 
+    m_interface (0)
+{
+  NS_LOG_FUNCTION (this);
+}
 
 ArpCache::~ArpCache ()
 {
+  NS_LOG_FUNCTION (this);
+}
+
+void 
+ArpCache::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
   Flush ();
+  m_device = 0;
+  m_interface = 0;
+  Object::DoDispose ();
+}
+
+void
+ArpCache::SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
+{
+  m_device = device;
+  m_interface = interface;
 }
 
 Ptr<NetDevice>
@@ -117,8 +166,7 @@
 
 ArpCache::Entry::Entry (ArpCache *arp)
   : m_arp (arp),
-    m_state (ALIVE),
-    m_waiting ()
+    m_state (ALIVE)
 {}
 
 
@@ -143,23 +191,18 @@
 ArpCache::Entry::MarkDead (void) 
 {
   m_state = DEAD;
-  //NS_ASSERT (m_waiting != 0);
   UpdateSeen ();
 }
-Ptr<Packet>
+void
 ArpCache::Entry::MarkAlive (Address macAddress) 
 {
   NS_ASSERT (m_state == WAIT_REPLY);
-  //NS_ASSERT (m_waiting != 0);
   m_macAddress = macAddress;
   m_state = ALIVE;
   UpdateSeen ();
-  Ptr<Packet> waiting = m_waiting;
-  //m_waiting = 0;
-  return waiting;
 }
 
-Ptr<Packet>
+bool
 ArpCache::Entry::UpdateWaitReply (Ptr<Packet> waiting)
 {
   NS_ASSERT (m_state == WAIT_REPLY);
@@ -167,17 +210,20 @@
    * we dump the previously waiting packet and
    * replace it with this one.
    */
-  Ptr<Packet> old = m_waiting;
-  m_waiting = waiting;
-  return old;
+  if (m_pending.size () >= m_arp->m_pendingQueueSize)
+    {
+      return false;
+    }
+  m_pending.push_back (waiting);
+  return true;
 }
 void 
 ArpCache::Entry::MarkWaitReply (Ptr<Packet> waiting)
 {
   NS_ASSERT (m_state == ALIVE || m_state == DEAD);
-  //NS_ASSERT (m_waiting == 0);
+  NS_ASSERT (m_pending.empty ());
   m_state = WAIT_REPLY;
-  m_waiting = waiting;
+  m_pending.push_back (waiting);
   UpdateSeen ();
 }
 
@@ -217,6 +263,20 @@
       return false;
     }
 }
+Ptr<Packet> 
+ArpCache::Entry::DequeuePending (void)
+{
+  if (m_pending.empty ())
+    {
+      return 0;
+    }
+  else
+    {
+      Ptr<Packet> p = m_pending.front ();
+      m_pending.pop_front ();
+      return p;
+    }
+}
 void 
 ArpCache::Entry::UpdateSeen (void)
 {
--- a/src/internet-node/arp-cache.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-cache.h	Wed Jun 04 17:19:32 2008 -0400
@@ -21,12 +21,14 @@
 #define ARP_CACHE_H
 
 #include <stdint.h>
+#include <list>
 #include "ns3/packet.h"
 #include "ns3/nstime.h"
 #include "ns3/net-device.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/address.h"
 #include "ns3/ptr.h"
+#include "ns3/object.h"
 #include "sgi-hashmap.h"
 
 namespace ns3 {
@@ -40,15 +42,19 @@
  * A cached lookup table for translating layer 3 addresses to layer 2.
  * This implementation does lookups from IPv4 to a MAC address
  */
-class ArpCache {
+class ArpCache : public Object
+{
 public:
+  static TypeId GetTypeId (void);
   class Entry;
+  ArpCache ();
+  ~ArpCache ();
+
   /**
    * \param device The hardware NetDevice associated with this ARP chache
    * \param interface the Ipv4Interface associated with this ARP chache
    */
-  ArpCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
-  ~ArpCache ();
+  void SetDevice (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
   /**
    * \return The NetDevice that this ARP cache is associated with
    */
@@ -98,9 +104,8 @@
     void MarkDead (void);
     /**
      * \param macAddress
-     * \return 
      */
-    Ptr<Packet> MarkAlive (Address macAddress);
+    void MarkAlive (Address macAddress);
     /**
      * \param waiting
      */
@@ -109,7 +114,7 @@
      * \param waiting
      * \return 
      */
-    Ptr<Packet> UpdateWaitReply (Ptr<Packet> waiting);
+    bool UpdateWaitReply (Ptr<Packet> waiting);
     /**
      * \return True if the state of this entry is dead; false otherwise.
      */
@@ -131,6 +136,12 @@
      * \return True if this entry has timedout; false otherwise.
      */
     bool IsExpired (void);
+
+    /**
+     * \returns 0 is no packet is pending, the next packet to send if 
+     *            packets are pending.
+     */
+    Ptr<Packet> DequeuePending (void);
   private:
     enum ArpCacheEntryState_e {
       ALIVE,
@@ -143,18 +154,21 @@
     ArpCacheEntryState_e m_state;
     Time m_lastSeen;
     Address m_macAddress;
-    Ptr<Packet> m_waiting;
+    std::list<Ptr<Packet> > m_pending;
   };
 
 private:
   typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash> Cache;
   typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash>::iterator CacheI;
 
+  virtual void DoDispose (void);
+
   Ptr<NetDevice> m_device;
   Ptr<Ipv4Interface> m_interface;
   Time m_aliveTimeout;
   Time m_deadTimeout;
   Time m_waitReplyTimeout;
+  uint32_t m_pendingQueueSize;
   Cache m_arpCache;
 };
 
--- a/src/internet-node/arp-ipv4-interface.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-ipv4-interface.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -24,41 +24,64 @@
 #include "ns3/node.h"
 #include "ns3/net-device.h"
 #include "ns3/address.h"
+#include "ns3/pointer.h"
 
 #include "arp-ipv4-interface.h"
 #include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
+#include "arp-cache.h"
 
 NS_LOG_COMPONENT_DEFINE ("ArpIpv4Interface");
 
 namespace ns3 {
 
-ArpIpv4Interface::ArpIpv4Interface ()
+TypeId 
+ArpIpv4Interface::GetTypeId (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  static TypeId tid = TypeId ("ns3::ArpIpv4Interface")
+    .SetParent<Ipv4Interface> ()
+    .AddAttribute ("ArpCache",
+                   "The arp cache for this ipv4 interface",
+                   PointerValue (0),
+                   MakePointerAccessor (&ArpIpv4Interface::m_cache),
+                   MakePointerChecker<ArpIpv4Interface> ())
+    ;
+  return tid;
+}
+
+ArpIpv4Interface::ArpIpv4Interface ()
+  : m_node (0),
+    m_device (0)
+{
+  NS_LOG_FUNCTION (this);
 }
 
 ArpIpv4Interface::~ArpIpv4Interface ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 void 
 ArpIpv4Interface::DoDispose (void)
 {
+  NS_LOG_FUNCTION (this);
   m_node = 0;
   m_device = 0;
+  m_cache = 0;
+  Ipv4Interface::DoDispose ();
 }
 
 void 
 ArpIpv4Interface::SetNode (Ptr<Node> node)
 {
   m_node = node;
+  DoSetup ();
 }
 void 
 ArpIpv4Interface::SetDevice (Ptr<NetDevice> device)
 {
   m_device = device;
+  DoSetup ();
 }
 
 Ptr<NetDevice> 
@@ -67,13 +90,24 @@
   return m_device;
 }
 
+void
+ArpIpv4Interface::DoSetup (void)
+{
+  if (m_node == 0 || m_device == 0)
+    {
+      return;
+    }
+  Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
+  m_cache = arp->CreateCache (m_device, this);
+}
+
 void 
 ArpIpv4Interface::SendTo (Ptr<Packet> p, Ipv4Address dest)
 {
   NS_LOG_FUNCTION (this << p << dest);
 
   NS_ASSERT (GetDevice () != 0);
-  if (GetDevice ()->NeedsArp ())
+  if (m_device->NeedsArp ())
     {
       NS_LOG_LOGIC ("Needs ARP");
       Ptr<ArpL3Protocol> arp = 
@@ -101,7 +135,7 @@
       else
         {
           NS_LOG_LOGIC ("ARP Lookup");
-          found = arp->Lookup (p, dest, GetDevice (), &hardwareDestination);
+          found = arp->Lookup (p, dest, GetDevice (), m_cache, &hardwareDestination);
         }
 
       if (found)
--- a/src/internet-node/arp-ipv4-interface.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-ipv4-interface.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,7 @@
 namespace ns3 {
 
 class Node;
+class ArpCache;
 
 /**
  * \brief an Ipv4 Interface which uses ARP
@@ -37,7 +38,9 @@
  */
 class ArpIpv4Interface : public Ipv4Interface
 {
- public:
+public:
+  static TypeId GetTypeId (void);
+
   ArpIpv4Interface ();
   virtual ~ArpIpv4Interface ();
 
@@ -49,8 +52,10 @@
 private:
   virtual void SendTo (Ptr<Packet> p, Ipv4Address dest);
   virtual void DoDispose (void);
+  void DoSetup (void);
   Ptr<Node> m_node;
   Ptr<NetDevice> m_device;
+  Ptr<ArpCache> m_cache;
 };
 
 }//namespace ns3
--- a/src/internet-node/arp-l3-protocol.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-l3-protocol.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -21,6 +21,8 @@
 #include "ns3/log.h"
 #include "ns3/node.h"
 #include "ns3/net-device.h"
+#include "ns3/object-vector.h"
+#include "ns3/trace-source-accessor.h"
 
 #include "ipv4-l3-protocol.h"
 #include "arp-l3-protocol.h"
@@ -41,18 +43,26 @@
 {
   static TypeId tid = TypeId ("ns3::ArpL3Protocol")
     .SetParent<Object> ()
+    .AddAttribute ("CacheList",
+                   "The list of ARP caches",
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList),
+                   MakeObjectVectorChecker<ArpCache> ())
+    .AddTraceSource ("Drop",
+                     "Packet dropped because not enough room in pending queue for a specific cache entry.",
+                     MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace))
     ;
   return tid;
 }
 
 ArpL3Protocol::ArpL3Protocol ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 ArpL3Protocol::~ArpL3Protocol ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 void 
@@ -64,17 +74,30 @@
 void 
 ArpL3Protocol::DoDispose (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
-  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
+  NS_LOG_FUNCTION (this);
+  for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
     {
-      delete *i;
+      Ptr<ArpCache> cache = *i;
+      cache->Dispose ();
     }
   m_cacheList.clear ();
   m_node = 0;
   Object::DoDispose ();
 }
 
-ArpCache *
+Ptr<ArpCache> 
+ArpL3Protocol::CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
+{
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  Ptr<ArpCache> cache = CreateObject<ArpCache> ();
+  cache->SetDevice (device, interface);
+  NS_ASSERT (device->IsBroadcast ());
+  device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
+  m_cacheList.push_back (cache);
+  return cache;
+}
+
+Ptr<ArpCache>
 ArpL3Protocol::FindCache (Ptr<NetDevice> device)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -85,20 +108,16 @@
 	  return *i;
 	}
     }
-  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
-  Ptr<Ipv4Interface> interface = ipv4->FindInterfaceForDevice (device);
-  ArpCache * cache = new ArpCache (device, interface);
-  NS_ASSERT (device->IsBroadcast ());
-  device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
-  m_cacheList.push_back (cache);
-  return cache;
+  NS_ASSERT (false);
+  // quiet compiler
+  return 0;
 }
 
 void 
 ArpL3Protocol::Receive(Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  ArpCache *cache = FindCache (device);
+  Ptr<ArpCache> cache = FindCache (device);
   ArpHeader arp;
   packet->RemoveHeader (arp);
   
@@ -135,8 +154,14 @@
                         arp.GetSourceIpv4Address ()
                      << " for waiting entry -- flush");
               Address from_mac = arp.GetSourceHardwareAddress ();
-              Ptr<Packet> waiting = entry->MarkAlive (from_mac);
-	      cache->GetInterface ()->Send (waiting, arp.GetSourceIpv4Address ());
+              entry->MarkAlive (from_mac);
+              Ptr<Packet> pending = entry->DequeuePending();
+              while (pending != 0)
+                {
+                  cache->GetInterface ()->Send (pending,
+                                                arp.GetSourceIpv4Address ());
+                  pending = entry->DequeuePending();
+                }
             } 
           else 
             {
@@ -145,13 +170,13 @@
               NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " << 
                         arp.GetSourceIpv4Address () << 
                         " for non-waiting entry -- drop");
-	      // XXX report packet as dropped.
+              m_dropTrace (packet);
             }
         } 
       else 
         {
           NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
-	  // XXX report packet as dropped.
+          m_dropTrace (packet);
         }
     }
   else
@@ -164,10 +189,10 @@
 bool 
 ArpL3Protocol::Lookup (Ptr<Packet> packet, Ipv4Address destination, 
                        Ptr<NetDevice> device,
+                       Ptr<ArpCache> cache,
                        Address *hardwareDestination)
 {
   NS_LOG_FUNCTION_NOARGS ();
-  ArpCache *cache = FindCache (device);
   ArpCache::Entry *entry = cache->Lookup (destination);
   if (entry != 0)
     {
@@ -192,7 +217,13 @@
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
                         ", wait reply for " << destination << " expired -- drop");
               entry->MarkDead ();
-	      // XXX report packet as 'dropped'
+              Ptr<Packet> pending = entry->DequeuePending();
+              while (pending != 0)
+                {
+                  m_dropTrace (pending);
+                  pending = entry->DequeuePending();
+                }
+              m_dropTrace (packet);
             }
         } 
       else 
@@ -200,25 +231,26 @@
           if (entry->IsDead ()) 
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
-                        ", dead entry for " << destination << " valid -- drop");
-	      // XXX report packet as 'dropped'
+                            ", dead entry for " << destination << " valid -- drop");
+              m_dropTrace (packet);
             } 
           else if (entry->IsAlive ()) 
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
-                        ", alive entry for " << destination << " valid -- send");
+                            ", alive entry for " << destination << " valid -- send");
 	      *hardwareDestination = entry->GetMacAddress ();
               return true;
             } 
           else if (entry->IsWaitReply ()) 
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
-                        ", wait reply for " << destination << " valid -- drop previous");
-              Ptr<Packet> old = entry->UpdateWaitReply (packet);
-	      // XXX report 'old' packet as 'dropped'
+                            ", wait reply for " << destination << " valid -- drop previous");
+              if (!entry->UpdateWaitReply (packet))
+                {
+                  m_dropTrace (packet);
+                }
             }
         }
-
     }
   else
     {
@@ -233,7 +265,7 @@
 }
 
 void
-ArpL3Protocol::SendArpRequest (ArpCache const *cache, Ipv4Address to)
+ArpL3Protocol::SendArpRequest (Ptr<const ArpCache> cache, Ipv4Address to)
 {
   NS_LOG_FUNCTION_NOARGS ();
   ArpHeader arp;
@@ -252,7 +284,7 @@
 }
 
 void
-ArpL3Protocol::SendArpReply (ArpCache const *cache, Ipv4Address toIp, Address toMac)
+ArpL3Protocol::SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac)
 {
   NS_LOG_FUNCTION_NOARGS ();
   ArpHeader arp;
--- a/src/internet-node/arp-l3-protocol.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/arp-l3-protocol.h	Wed Jun 04 17:19:32 2008 -0400
@@ -24,6 +24,9 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/address.h"
 #include "ns3/ptr.h"
+#include "ns3/traced-callback.h"
+
+#include "ipv4-interface.h"
 
 namespace ns3 {
 
@@ -31,7 +34,7 @@
 class NetDevice;
 class Node;
 class Packet;
-class TraceContext;
+
 /**
  * \brief An implementation of the ARP protocol
  */
@@ -46,6 +49,8 @@
 
   void SetNode (Ptr<Node> node);
 
+  Ptr<ArpCache> CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
+
   /**
    * \brief Recieve a packet
    */
@@ -55,21 +60,24 @@
    * \param p
    * \param destination
    * \param device
+   * \param cache
    * \param hardwareDestination
    * \return 
    */
   bool Lookup (Ptr<Packet> p, Ipv4Address destination, 
 	       Ptr<NetDevice> device,
+               Ptr<ArpCache> cache,
 	       Address *hardwareDestination);
 protected:
   virtual void DoDispose (void);
 private:
-  typedef std::list<ArpCache *> CacheList;
-  ArpCache *FindCache (Ptr<NetDevice> device);
-  void SendArpRequest (ArpCache const *cache, Ipv4Address to);
-  void SendArpReply (ArpCache const *cache, Ipv4Address toIp, Address toMac);
+  typedef std::list<Ptr<ArpCache> > CacheList;
+  Ptr<ArpCache> FindCache (Ptr<NetDevice> device);
+  void SendArpRequest (Ptr<const ArpCache>cache, Ipv4Address to);
+  void SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac);
   CacheList m_cacheList;
   Ptr<Node> m_node;
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
 };
 
 }//namespace ns3
--- a/src/internet-node/ascii-trace.cc	Fri May 30 15:31:50 2008 -0400
+++ /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 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 "ascii-trace.h"
-
-#include "ns3/config.h"
-#include "ns3/simulator.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/queue.h"
-
-namespace ns3 {
-
-AsciiTrace::AsciiTrace (std::string filename)
-{
-  m_os.open (filename.c_str ());
-}
-AsciiTrace::~AsciiTrace ()
-{
-  m_os.close ();
-}
-void
-AsciiTrace::TraceAllQueues (void)
-{
-  Packet::EnableMetadata ();
-  Config::Connect ("/NodeList/*/DeviceList/*/TxQueue/Enqueue",
-                              MakeCallback (&AsciiTrace::LogDevQueueEnqueue, this));
-  Config::Connect ("/NodeList/*/DeviceList/*/TxQueue/Dequeue",
-                              MakeCallback (&AsciiTrace::LogDevQueueDequeue, this));
-  Config::Connect ("/NodeList/*/DeviceList/*/TxQueue/Drop",
-                              MakeCallback (&AsciiTrace::LogDevQueueDrop, this));
-}
-void
-AsciiTrace::TraceAllNetDeviceRx (void)
-{
-  Packet::EnableMetadata ();
-  Config::Connect ("/NodeList/*/DeviceList/*/Rx",
-                              MakeCallback (&AsciiTrace::LogDevRx, this));
-}
-
-void 
-AsciiTrace::LogDevQueueEnqueue (std::string context,
-                                Ptr<const Packet> packet)
-{
-  m_os << "+ ";
-  m_os << Simulator::Now ().GetSeconds () << " ";
-  m_os << context;
-  m_os << " pkt-uid=" << packet->GetUid () << " ";
-  packet->Print (m_os);
-  m_os << std::endl;
-}
-
-void 
-AsciiTrace::LogDevQueueDequeue (std::string context,
-                                Ptr<const Packet> packet)
-{
-  m_os << "- ";
-  m_os << Simulator::Now ().GetSeconds () << " ";
-  m_os << context;
-  m_os << " pkt-uid=" << packet->GetUid () << " ";
-  packet->Print (m_os);
-  m_os << std::endl;
-}
-
-void 
-AsciiTrace::LogDevQueueDrop (std::string context,
-                             Ptr<const Packet> packet)
-{
-  m_os << "d ";
-  m_os << Simulator::Now ().GetSeconds () << " ";
-  m_os << context;
-  m_os << " pkt-uid=" << packet->GetUid () << " ";
-  packet->Print (m_os);
-  m_os << std::endl;
-}
-void 
-AsciiTrace::LogDevRx (std::string context,
-                      Ptr<const Packet> p)
-{
-  m_os << "r " << Simulator::Now ().GetSeconds () << " ";
-  m_os << context;
-  m_os << " pkt-uid=" << p->GetUid () << " ";
-  p->Print (m_os);
-  m_os << std::endl;  
-}
-
-}//namespace ns3
--- a/src/internet-node/ascii-trace.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/* -*-	Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 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>
- */
-#ifndef ASCII_TRACE_H
-#define ASCII_TRACE_H
-
-#include <string>
-#include <fstream>
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Packet;
-class TraceContext;
-
-class AsciiTrace 
-{
-public:
-  AsciiTrace (std::string filename);
-  ~AsciiTrace ();
-  void TraceAllQueues (void);
-  void TraceAllNetDeviceRx (void);
-private:
-  void LogDevQueueEnqueue (std::string context, Ptr<const Packet> p);
-  void LogDevQueueDequeue (std::string context, Ptr<const Packet> p);
-  void LogDevQueueDrop (std::string context, Ptr<const Packet> p);
-  void LogDevRx (std::string context, Ptr<const Packet> p);
-  std::ofstream m_os;
-};
-
-}//namespace ns3
-
-#endif /* ASCII_TRACE_H */
--- a/src/internet-node/internet-stack.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/internet-stack.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -40,12 +40,6 @@
   Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> ();
   ipv4->SetNode (node);
   arp->SetNode (node);
-  // XXX remove the PeekPointer below.
-  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, PeekPointer (ipv4)), 
-                                 Ipv4L3Protocol::PROT_NUMBER, 0);
-  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (arp)),
-                                 ArpL3Protocol::PROT_NUMBER, 0);
-
 
   Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> ();
   Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> ();
--- a/src/internet-node/ipv4-header.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,331 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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/assert.h"
-#include "ns3/log.h"
-#include "ns3/header.h"
-#include "ipv4-header.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4Header");
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (Ipv4Header);
-
-bool Ipv4Header::m_calcChecksum = false;
-
-Ipv4Header::Ipv4Header ()
-  : m_payloadSize (0),
-    m_identification (0),
-    m_tos (0),
-    m_ttl (0),
-    m_protocol (0),
-    m_flags (0),
-    m_fragmentOffset (0),
-    m_goodChecksum (true)
-{}
-
-void 
-Ipv4Header::EnableChecksums (void)
-{
-  m_calcChecksum = true;
-}
-
-void 
-Ipv4Header::SetPayloadSize (uint16_t size)
-{
-  m_payloadSize = size;
-}
-uint16_t 
-Ipv4Header::GetPayloadSize (void) const
-{
-  return m_payloadSize;
-}
-
-uint16_t 
-Ipv4Header::GetIdentification (void) const
-{
-  return m_identification;
-}
-void 
-Ipv4Header::SetIdentification (uint16_t identification)
-{
-  m_identification = identification;
-}
-
-
-
-void 
-Ipv4Header::SetTos (uint8_t tos)
-{
-  m_tos = tos;
-}
-uint8_t 
-Ipv4Header::GetTos (void) const
-{
-  return m_tos;
-}
-void 
-Ipv4Header::SetMoreFragments (void)
-{
-  m_flags |= MORE_FRAGMENTS;
-}
-void
-Ipv4Header::SetLastFragment (void)
-{
-  m_flags &= ~MORE_FRAGMENTS;
-}
-bool 
-Ipv4Header::IsLastFragment (void) const
-{
-  return !(m_flags & MORE_FRAGMENTS);
-}
-
-void 
-Ipv4Header::SetDontFragment (void)
-{
-  m_flags |= DONT_FRAGMENT;
-}
-void 
-Ipv4Header::SetMayFragment (void)
-{
-  m_flags &= ~DONT_FRAGMENT;
-}
-bool 
-Ipv4Header::IsDontFragment (void) const
-{
-  return (m_flags & DONT_FRAGMENT);
-}
-
-void 
-Ipv4Header::SetFragmentOffset (uint16_t offset)
-{
-  NS_ASSERT (!(offset & (~0x3fff)));
-  m_fragmentOffset = offset;
-}
-uint16_t 
-Ipv4Header::GetFragmentOffset (void) const
-{
-  NS_ASSERT (!(m_fragmentOffset & (~0x3fff)));
-  return m_fragmentOffset;
-}
-
-void 
-Ipv4Header::SetTtl (uint8_t ttl)
-{
-  m_ttl = ttl;
-}
-uint8_t 
-Ipv4Header::GetTtl (void) const
-{
-  return m_ttl;
-}
-  
-uint8_t 
-Ipv4Header::GetProtocol (void) const
-{
-  return m_protocol;
-}
-void 
-Ipv4Header::SetProtocol (uint8_t protocol)
-{
-  m_protocol = protocol;
-}
-
-void 
-Ipv4Header::SetSource (Ipv4Address source)
-{
-  m_source = source;
-}
-Ipv4Address
-Ipv4Header::GetSource (void) const
-{
-  return m_source;
-}
-
-void 
-Ipv4Header::SetDestination (Ipv4Address dst)
-{
-  m_destination = dst;
-}
-Ipv4Address
-Ipv4Header::GetDestination (void) const
-{
-  return m_destination;
-}
-
-
-bool
-Ipv4Header::IsChecksumOk (void) const
-{
-  return m_goodChecksum;
-}
-
-
-TypeId 
-Ipv4Header::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Ipv4Header")
-    .SetParent<Header> ()
-    .AddConstructor<Ipv4Header> ()
-    ;
-  return tid;
-}
-TypeId 
-Ipv4Header::GetInstanceTypeId (void) const
-{
-  return GetTypeId ();
-}
-void 
-Ipv4Header::Print (std::ostream &os) const
-{
-  // ipv4, right ?
-  std::string flags;
-  if (m_flags == 0)
-    {
-      flags = "none";
-    }
-  else if (m_flags & MORE_FRAGMENTS &&
-           m_flags & DONT_FRAGMENT)
-    {
-      flags = "MF|DF";
-    }
-  else if (m_flags & DONT_FRAGMENT)
-    {
-      flags = "DF";
-    }
-  else if (m_flags & MORE_FRAGMENTS)
-    {
-      flags = "MF";
-    }
-  else
-    {
-      flags = "XX";
-    }
-  os << "tos 0x" << std::hex << m_tos << std::dec << " "
-     << "ttl " << m_ttl << " "
-     << "id " << m_identification << " "
-     << "offset " << m_fragmentOffset << " "
-     << "flags [" << flags << "] "
-     << "length: " << (m_payloadSize + 5 * 4)
-     << " " 
-     << m_source << " > " << m_destination
-    ;
-}
-uint32_t 
-Ipv4Header::GetSerializedSize (void) const
-{
-  return 5 * 4;
-}
-
-void
-Ipv4Header::Serialize (Buffer::Iterator start) const
-{
-  Buffer::Iterator i = start;
-  
-  uint8_t verIhl = (4 << 4) | (5);
-  i.WriteU8 (verIhl);
-  i.WriteU8 (m_tos);
-  i.WriteHtonU16 (m_payloadSize + 5*4);
-  i.WriteHtonU16 (m_identification);
-  uint32_t fragmentOffset = m_fragmentOffset / 8;
-  uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
-  if (m_flags & DONT_FRAGMENT) 
-    {
-      flagsFrag |= (1<<6);
-    }
-  if (m_flags & MORE_FRAGMENTS) 
-    {
-      flagsFrag |= (1<<5);
-    }
-  i.WriteU8 (flagsFrag);
-  uint8_t frag = fragmentOffset & 0xff;
-  i.WriteU8 (frag);
-  i.WriteU8 (m_ttl);
-  i.WriteU8 (m_protocol);
-  i.WriteHtonU16 (0);
-  i.WriteHtonU32 (m_source.GetHostOrder ());
-  i.WriteHtonU32 (m_destination.GetHostOrder ());
-
-  if (m_calcChecksum) 
-    {
-#if 0
-      // XXX we need to add Buffer::Iterator::PeekData method
-      uint8_t *data = start.PeekData ();
-      uint16_t checksum = UtilsChecksumCalculate (0, data, GetSize ());
-      checksum = UtilsChecksumComplete (checksum);
-      NS_LOG_LOGIC ("checksum=" <<checksum);
-      i = start;
-      i.Next (10);
-      i.WriteU16 (checksum);
-#endif
-    }
-}
-uint32_t
-Ipv4Header::Deserialize (Buffer::Iterator start)
-{
-  Buffer::Iterator i = start;
-  uint8_t verIhl = i.ReadU8 ();
-  uint8_t ihl = verIhl & 0x0f; 
-  uint16_t headerSize = ihl * 4;
-  NS_ASSERT ((verIhl >> 4) == 4);
-  m_tos = i.ReadU8 ();
-  uint16_t size = i.ReadNtohU16 ();
-  m_payloadSize = size - headerSize;
-  m_identification = i.ReadNtohU16 ();
-  uint8_t flags = i.ReadU8 ();
-  m_flags = 0;
-  if (flags & (1<<6)) 
-    {
-      m_flags |= DONT_FRAGMENT;
-    }
-  if (flags & (1<<5)) 
-    {
-      m_flags |= MORE_FRAGMENTS;
-    }
-  //XXXX I think we should clear some bits in fragmentOffset !
-  i.Prev ();
-  m_fragmentOffset = i.ReadNtohU16 ();
-  m_fragmentOffset *= 8;
-  m_ttl = i.ReadU8 ();
-  m_protocol = i.ReadU8 ();
-  i.Next (2); // checksum
-  m_source.SetHostOrder (i.ReadNtohU32 ());
-  m_destination.SetHostOrder (i.ReadNtohU32 ());
-
-  if (m_calcChecksum) 
-    {
-#if 0
-      uint8_t *data = start.PeekData ();
-      uint16_t localChecksum = UtilsChecksumCalculate (0, data, headerSize);
-      if (localChecksum == 0xffff) 
-        {
-          m_goodChecksum = true;
-        } 
-      else 
-        {
-          m_goodChecksum = false;
-        }
-#endif
-    }
-  return GetSerializedSize ();
-}
-
-}; // namespace ns3
--- a/src/internet-node/ipv4-header.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005 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>
- */
-
-#ifndef IPV4_HEADER_H
-#define IPV4_HEADER_H
-
-#include "ns3/header.h"
-#include "ns3/ipv4-address.h"
-
-namespace ns3 {
-/**
- * \brief Packet header for IPv4
- */
-class Ipv4Header : public Header 
-{
-public:
-  /**
-   * \brief Construct a null IPv4 header
-   */
-  Ipv4Header ();
-  /**
-   * \brief Enable checksum calculation for IP (XXX currently has no effect)
-   */
-  static void EnableChecksums (void);
-  /**
-   * \param size the size of the payload in bytes
-   */
-  void SetPayloadSize (uint16_t size);
-  /**
-   * \param identification the Identification field of IPv4 packets.
-   *
-   * By default, set to zero.
-   */
-  void SetIdentification (uint16_t identification);
-  /**
-   * \param tos the 8 bits of Ipv4 TOS.
-   */
-  void SetTos (uint8_t tos);
-  /**
-   * This packet is not the last packet of a fragmented ipv4 packet.
-   */
-  void SetMoreFragments (void);
-  /**
-   * This packet is the last packet of a fragmented ipv4 packet.
-   */
-  void SetLastFragment (void);
-  /**
-   * Don't fragment this packet: if you need to anyway, drop it.
-   */
-  void SetDontFragment (void);
-  /**
-   * If you need to fragment this packet, you can do it.
-   */
-  void SetMayFragment (void);
-  /**
-   * \param offset the ipv4 fragment offset
-   */
-  void SetFragmentOffset (uint16_t offset);
-  /**
-   * \param ttl the ipv4 TTL
-   */
-  void SetTtl (uint8_t ttl);
-  /**
-   * \param num the ipv4 protocol field
-   */
-  void SetProtocol (uint8_t num);
-  /**
-   * \param source the source of this packet
-   */
-  void SetSource (Ipv4Address source);
-  /**
-   * \param destination the destination of this packet.
-   */
-  void SetDestination (Ipv4Address destination);
-  /**
-   * \returns the size of the payload in bytes
-   */
-  uint16_t GetPayloadSize (void) const;
-  /**
-   * \returns the identification field of this packet.
-   */
-  uint16_t GetIdentification (void) const;
-  /**
-   * \returns the TOS field of this packet.
-   */
-  uint8_t GetTos (void) const;
-  /**
-   * \returns true if this is the last fragment of a packet, false otherwise.
-   */
-  bool IsLastFragment (void) const;
-  /**
-   * \returns true if this is this packet can be fragmented.
-   */  
-  bool IsDontFragment (void) const;
-  /**
-   * \returns the offset of this fragment.
-   */
-  uint16_t GetFragmentOffset (void) const;
-  /**
-   * \returns the TTL field of this packet
-   */
-  uint8_t GetTtl (void) const;
-  /**
-   * \returns the protocol field of this packet
-   */
-  uint8_t GetProtocol (void) const;
-  /**
-   * \returns the source address of this packet
-   */
-  Ipv4Address GetSource (void) const;
-  /**
-   * \returns the destination address of this packet
-   */
-  Ipv4Address GetDestination (void) const;
-  
-  /**
-   * \returns true if the upv4 checksum is correct, false otherwise.
-   *
-   * If Ipv4Header::EnableChecksums has not been called prior to
-   * creating this packet, this method will always return true.
-   */
-  bool IsChecksumOk (void) const;
-
-  static TypeId GetTypeId (void);
-  virtual TypeId GetInstanceTypeId (void) const;
-  virtual void Print (std::ostream &os) const;
-  virtual uint32_t GetSerializedSize (void) const;
-  virtual void Serialize (Buffer::Iterator start) const;
-  virtual uint32_t Deserialize (Buffer::Iterator start);
-private:
-
-  enum FlagsE {
-    DONT_FRAGMENT = (1<<0),
-    MORE_FRAGMENTS = (1<<1)
-  };
-
-  static bool m_calcChecksum;
-
-  uint16_t m_payloadSize;
-  uint16_t m_identification;
-  uint32_t m_tos : 8;
-  uint32_t m_ttl : 8;
-  uint32_t m_protocol : 8;
-  uint32_t m_flags : 3;
-  uint16_t m_fragmentOffset : 13;
-  Ipv4Address m_source;
-  Ipv4Address m_destination;
-  bool m_goodChecksum;
-};
-
-} // namespace ns3
-
-
-#endif /* IPV4_HEADER_H */
--- a/src/internet-node/ipv4-interface.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-interface.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -80,8 +80,8 @@
 Ipv4Interface::GetBroadcast (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
-  uint32_t mask = m_netmask.GetHostOrder ();
-  uint32_t address = m_address.GetHostOrder ();
+  uint32_t mask = m_netmask.Get ();
+  uint32_t address = m_address.Get ();
   Ipv4Address broadcast = Ipv4Address (address | (~mask));
   return broadcast;
 }
--- a/src/internet-node/ipv4-interface.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-interface.h	Wed Jun 04 17:19:32 2008 -0400
@@ -31,7 +31,6 @@
 
 class NetDevice;
 class Packet;
-class TraceContext;
 
 /**
  * \brief The IPv4 representation of a network interface
--- a/src/internet-node/ipv4-l3-protocol.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-l3-protocol.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -29,10 +29,11 @@
 #include "ns3/uinteger.h"
 #include "ns3/trace-source-accessor.h"
 #include "ns3/object-vector.h"
+#include "ns3/ipv4-header.h"
+#include "arp-l3-protocol.h"
 
 #include "ipv4-l3-protocol.h"
 #include "ipv4-l4-protocol.h"
-#include "ipv4-header.h"
 #include "ipv4-interface.h"
 #include "ipv4-loopback-interface.h"
 #include "arp-ipv4-interface.h"
@@ -81,7 +82,7 @@
 
 Ipv4L3Protocol::~Ipv4L3Protocol ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 void
@@ -94,7 +95,12 @@
 void 
 Ipv4L3Protocol::DoDispose (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
+  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
+    {
+      Ptr<Ipv4Interface> interface = *i;
+      interface->Dispose ();
+    }
   m_interfaces.clear ();
   m_node = 0;
   m_staticRouting->Dispose ();
@@ -315,6 +321,13 @@
 Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
 {
   NS_LOG_FUNCTION (this << &device);
+
+  Ptr<Node> node = GetObject<Node> ();
+  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), 
+                                 Ipv4L3Protocol::PROT_NUMBER, device);
+  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
+                                 ArpL3Protocol::PROT_NUMBER, device);
+
   Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
   interface->SetNode (m_node);
   interface->SetDevice (device);
@@ -490,9 +503,7 @@
   // Set TTL to 1 if it is a broadcast packet of any type.  Otherwise,
   // possibly override the default TTL if the packet is tagged
   SocketIpTtlTag tag;
-  bool found = packet->PeekTag (tag);
-  uint8_t socketTtl = tag.GetTtl ();
-  packet->RemoveTag (tag);
+  bool found = packet->FindFirstMatchingTag (tag);
 
   if (destination.IsBroadcast ()) 
     {
@@ -500,7 +511,8 @@
     }
   else if (found)
     {
-      ipHeader.SetTtl (socketTtl);
+      ipHeader.SetTtl (tag.GetTtl ());
+      // XXX remove tag here?  
     }
   else
     {
--- a/src/internet-node/ipv4-l3-protocol.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-l3-protocol.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,7 +27,7 @@
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
 #include "ns3/traced-callback.h"
-#include "ipv4-header.h"
+#include "ns3/ipv4-header.h"
 #include "ipv4-static-routing.h"
 
 namespace ns3 {
--- a/src/internet-node/ipv4-l4-demux.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-l4-demux.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,7 +32,6 @@
 
 class Ipv4L4Protocol;
 class Node;
-class TraceContext;
 
 /**
  * \brief L4 Ipv4 Demux
--- a/src/internet-node/ipv4-l4-protocol.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-l4-protocol.h	Wed Jun 04 17:19:32 2008 -0400
@@ -31,8 +31,6 @@
 
 class Packet;
 class Ipv4Address;
-class TraceResolver;
-class TraceContext;
 
 /**
  * \brief L4 Protocol base class 
--- a/src/internet-node/ipv4-loopback-interface.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-loopback-interface.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -31,15 +31,24 @@
 
 namespace ns3 {
 
+TypeId 
+Ipv4LoopbackInterface::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4LoopbackInterface")
+    .SetParent<Ipv4Interface> ()
+    ;
+  return tid;
+}
+
 Ipv4LoopbackInterface::Ipv4LoopbackInterface ()
   : m_node (0)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 Ipv4LoopbackInterface::~Ipv4LoopbackInterface ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
   NS_ASSERT (m_node != 0);
 }
 
--- a/src/internet-node/ipv4-loopback-interface.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-loopback-interface.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,7 +32,8 @@
  */
 class Ipv4LoopbackInterface : public Ipv4Interface 
 {
- public:
+public:
+  static TypeId GetTypeId (void);
   Ipv4LoopbackInterface ();
   virtual ~Ipv4LoopbackInterface ();
 
--- a/src/internet-node/ipv4-static-routing.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/ipv4-static-routing.h	Wed Jun 04 17:19:32 2008 -0400
@@ -25,7 +25,7 @@
 #include <list>
 #include <stdint.h>
 #include "ns3/ipv4-address.h"
-#include "ipv4-header.h"
+#include "ns3/ipv4-header.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
 
--- a/src/internet-node/pcap-trace.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/* -*-	Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 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 "pcap-trace.h"
-
-#include <sstream>
-
-#include "ns3/config.h"
-#include "ns3/callback.h"
-#include "ns3/pcap-writer.h"
-#include "ns3/node-list.h"
-#include "ns3/node.h"
-#include "ns3/packet.h"
-#include "ns3/log.h"
-
-#include "ipv4-l3-protocol.h"
-
-NS_LOG_COMPONENT_DEFINE ("PcapTrace");
-
-namespace ns3 {
-
-
-PcapTrace::PcapTrace (std::string filename)
-  : m_filename (filename)
-{}
-PcapTrace::~PcapTrace ()
-{
-  for (std::vector<Trace>::iterator i = m_traces.begin ();
-       i != m_traces.end (); i++)
-    {
-      delete i->writer;
-    }
-}
-
-void 
-PcapTrace::TraceAllIp (void)
-{
-  Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Tx",
-                              MakeCallback (&PcapTrace::LogTxIp, this));
-  Config::Connect ("/NodeList/*/$ns3::Ipv4L3Protocol/Rx",
-                              MakeCallback (&PcapTrace::LogRxIp, this));
-}
-
-PcapWriter *
-PcapTrace::GetStream (uint32_t nodeId, uint32_t interfaceId)
-{
-  for (std::vector<Trace>::iterator i = m_traces.begin ();
-       i != m_traces.end (); i++)
-    {
-      if (i->nodeId == nodeId &&
-	  i->interfaceId == interfaceId)
-	{
-	  return i->writer;
-	}
-    }
-  PcapTrace::Trace trace;
-  trace.nodeId = nodeId;
-  trace.interfaceId = interfaceId;
-  trace.writer = new PcapWriter ();
-  std::ostringstream oss;
-  oss << m_filename << "-" << nodeId << "-" << interfaceId;
-  std::string filename = oss.str ();
-  trace.writer->Open (filename);
-  trace.writer->WriteIpHeader ();
-  m_traces.push_back (trace);
-  return trace.writer;
-}
-
-uint32_t
-PcapTrace::GetNodeIndex (std::string context) const
-{
-  std::string::size_type pos;
-  pos = context.find ("/NodeList/");
-  NS_ASSERT (pos == 0);
-  std::string::size_type afterNodeIndex = context.find ("/", 11);
-  NS_ASSERT (afterNodeIndex != std::string::npos);
-  std::string index = context.substr (10, afterNodeIndex - 10);
-  NS_LOG_DEBUG ("index="<<index);
-  std::istringstream iss;
-  iss.str (index);
-  uint32_t nodeIndex;
-  iss >> nodeIndex;
-  return nodeIndex;
-}  
-
-void 
-PcapTrace::LogTxIp (std::string context, Ptr<const Packet> p, uint32_t interfaceIndex)
-{
-  PcapWriter *writer = GetStream (GetNodeIndex (context), interfaceIndex);
-  writer->WritePacket (p);
-}
-
-void 
-PcapTrace::LogRxIp (std::string context, Ptr<const Packet> p, uint32_t interfaceIndex)
-{
-  PcapWriter *writer = GetStream (GetNodeIndex (context), interfaceIndex);
-  writer->WritePacket (p);
-}
-
-
-}//namespace ns3
--- a/src/internet-node/pcap-trace.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/* -*-	Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 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>
- */
-#ifndef PCAP_TRACE_H
-#define PCAP_TRACE_H
-
-#include <string>
-#include <vector>
-#include "ns3/ptr.h"
-
-namespace ns3 {
-
-class Packet;
-class TraceContext;
-class PcapWriter;
-
-class PcapTrace 
-{
-public:
-  PcapTrace (std::string filename);
-  ~PcapTrace ();
-
-  void TraceAllIp (void);
-private:
-  PcapWriter *GetStream (uint32_t nodeId, uint32_t interfaceId);
-  void LogRxIp (std::string context, Ptr<const Packet> p, uint32_t interfaceIndex);
-  void LogTxIp (std::string context, Ptr<const Packet> p, uint32_t interfaceIndex);
-  uint32_t GetNodeIndex (std::string context) const;
-  std::string m_filename;
-  struct Trace {
-    uint32_t nodeId;
-    uint32_t interfaceId;
-    PcapWriter *writer;
-  };
-  std::vector<Trace> m_traces;
-};
-
-}//namespace ns3
-
-#endif /* PCAP_TRACE_H */
--- a/src/internet-node/tcp-l4-protocol.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/tcp-l4-protocol.h	Wed Jun 04 17:19:32 2008 -0400
@@ -37,7 +37,6 @@
 namespace ns3 {
 
 class Node;
-class TraceContext;
 class Socket;
 class TcpHeader;
 /**
--- a/src/internet-node/tcp-socket-factory-impl.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/tcp-socket-factory-impl.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,7 +30,9 @@
 /**
  * \ingroup internetNode
  * \defgroup Tcp Tcp
- *
+ */
+/**
+ * \ingroup Tcp
  * \section Tcp Overview
  *
  * The TCP code in ns3::InternetNode is ported from the  
--- a/src/internet-node/tcp-socket-impl.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/tcp-socket-impl.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -125,7 +125,9 @@
     m_lastMeasuredRtt (Seconds(0.0)),
     m_cnTimeout (sock.m_cnTimeout),
     m_cnCount (sock.m_cnCount),
-    m_rxAvailable (0)
+    m_rxAvailable (0),
+    m_wouldBlock (false),
+    m_sndBufSize (sock.m_sndBufSize)
 {
   NS_LOG_FUNCTION_NOARGS ();
   NS_LOG_LOGIC("Invoked the copy constructor");
@@ -500,14 +502,11 @@
       return 0;
     }
   Ptr<Packet> outPacket = Create<Packet>();
-  SocketRxAddressTag tag;     //Packet AddAt* APIs don't preserve tags
-  out.begin()->second->PeekTag (tag); //XXX so manually copy the address tag
-  outPacket->AddTag (tag);
   for(i = out.begin(); i!=out.end(); ++i)
   {
     if (outPacket->GetSize() + i->second->GetSize() <= maxSize )
     {
-      outPacket->AddAtEnd(i->second); //XXX this doesn't copy the tags
+      outPacket->AddAtEnd(i->second);
     }
     else
     {
--- a/src/internet-node/udp-l4-protocol.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/udp-l4-protocol.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,7 +32,6 @@
 namespace ns3 {
 
 class Node;
-class TraceContext;
 class Socket;
 /**
  * \brief Implementation of the UDP protocol
--- a/src/internet-node/udp-socket-impl.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/udp-socket-impl.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -133,8 +133,8 @@
     {
       return -1;
     }
-  m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, this));
-  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, this));
+  m_endPoint->SetRxCallback (MakeCallback (&UdpSocketImpl::ForwardUp, Ptr<UdpSocketImpl> (this)));
+  m_endPoint->SetDestroyCallback (MakeCallback (&UdpSocketImpl::Destroy, Ptr<UdpSocketImpl> (this)));
   return 0;
 }
 
@@ -217,6 +217,13 @@
 }
 
 int 
+UdpSocketImpl::Listen (uint32_t queueLimit)
+{
+  m_errno = Socket::ERROR_OPNOTSUPP;
+  return -1;
+}
+
+int 
 UdpSocketImpl::Send (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION (this << p);
@@ -530,14 +537,16 @@
 
 void UdpSocketImplTest::ReceivePkt (Ptr<Socket> socket)
 {
-  uint32_t availableData = socket->GetRxAvailable ();
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
   m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
   NS_ASSERT (availableData == m_receivedPacket->GetSize ());
 }
 
 void UdpSocketImplTest::ReceivePkt2 (Ptr<Socket> socket)
 {
-  uint32_t availableData = socket->GetRxAvailable ();
+  uint32_t availableData;
+  availableData = socket->GetRxAvailable ();
   m_receivedPacket2 = socket->Recv (std::numeric_limits<uint32_t>::max(), 0);
   NS_ASSERT (availableData == m_receivedPacket2->GetSize ());
 }
--- a/src/internet-node/udp-socket-impl.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/udp-socket-impl.h	Wed Jun 04 17:19:32 2008 -0400
@@ -57,6 +57,7 @@
   virtual int ShutdownSend (void);
   virtual int ShutdownRecv (void);
   virtual int Connect(const Address &address);
+  virtual int Listen (uint32_t queueLimit);
   virtual int Send (Ptr<Packet> p);
   virtual int SendTo (Ptr<Packet> p, const Address &address);
   virtual uint32_t GetTxAvailable (void) const;
--- a/src/internet-node/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/internet-node/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -7,7 +7,6 @@
         'internet-stack.cc',
         'ipv4-l4-demux.cc',
         'ipv4-l4-protocol.cc',
-        'ipv4-header.cc',
         'udp-header.cc',
         'tcp-header.cc',
         'ipv4-checksum.cc',
@@ -26,8 +25,6 @@
         'tcp-socket-impl.cc',
         'ipv4-end-point-demux.cc',
         'ipv4-impl.cc',
-        'ascii-trace.cc',
-        'pcap-trace.cc',
         'udp-socket-factory-impl.cc',
         'tcp-socket-factory-impl.cc',
         'pending-data.cc',
@@ -39,9 +36,6 @@
     headers.module = 'internet-node'
     headers.source = [
         'internet-stack.h',
-        'ascii-trace.h',
-        'pcap-trace.h',
-        'ipv4-header.h',
         'udp-header.h',
         'tcp-header.h',
         'sequence-number.h',
--- a/src/mobility/hierarchical-mobility-model.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/hierarchical-mobility-model.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -18,7 +18,6 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "hierarchical-mobility-model.h"
-#include "mobility-model-notifier.h"
 #include "ns3/pointer.h"
 
 namespace ns3 {
@@ -33,11 +32,13 @@
     .AddConstructor<HierarchicalMobilityModel> ()
     .AddAttribute ("Child", "The child mobility model.",
                    PointerValue (),
-                   MakePointerAccessor (&HierarchicalMobilityModel::SetChild),
+                   MakePointerAccessor (&HierarchicalMobilityModel::SetChild,
+                                        &HierarchicalMobilityModel::GetChild),
                    MakePointerChecker<MobilityModel> ())
     .AddAttribute ("Parent", "The parent mobility model.",
                    PointerValue (),
-                   MakePointerAccessor (&HierarchicalMobilityModel::SetParent),
+                   MakePointerAccessor (&HierarchicalMobilityModel::SetParent,
+                                        &HierarchicalMobilityModel::GetParent),
                    MakePointerChecker<MobilityModel> ())
     ;
   return tid;
@@ -52,28 +53,14 @@
 HierarchicalMobilityModel::SetChild (Ptr<MobilityModel> model)
 {
   m_child = model;
-  Ptr<MobilityModelNotifier> notifier = 
-    m_child->GetObject<MobilityModelNotifier> ();
-  if (notifier == 0)
-    {
-      notifier = CreateObject<MobilityModelNotifier> ();
-      m_child->AggregateObject (notifier);
-    }
-  notifier->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+  m_child->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
 }
 
 void 
 HierarchicalMobilityModel::SetParent (Ptr<MobilityModel> model)
 {
   m_parent = model;
-  Ptr<MobilityModelNotifier> notifier = 
-    m_parent->GetObject<MobilityModelNotifier> ();
-  if (notifier == 0)
-    {
-      notifier = CreateObject<MobilityModelNotifier> ();
-      m_parent->AggregateObject (notifier);
-    }
-  notifier->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+  m_parent->TraceConnectWithoutContext ("CourseChange", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
 }
 
 
--- a/src/mobility/mobility-model-notifier.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 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 "mobility-model-notifier.h"
-#include "ns3/trace-source-accessor.h"
-
-namespace ns3 {
-
-TypeId 
-MobilityModelNotifier::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("MobilityModelNotifier")
-    .SetParent<Object> ()
-    .AddConstructor<MobilityModelNotifier> ()
-    .AddTraceSource ("CourseChange", 
-                     "The value of the position and/or velocity vector changed",
-                     MakeTraceSourceAccessor (&MobilityModelNotifier::m_trace))
-    ;
-  return tid;
-}
-
-MobilityModelNotifier::MobilityModelNotifier ()
-{}
-
-void 
-MobilityModelNotifier::Notify (Ptr<const MobilityModel> position) const
-{
-  m_trace (position);
-}
-
-} // namespace ns3
--- a/src/mobility/mobility-model-notifier.h	Fri May 30 15:31:50 2008 -0400
+++ /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) 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>
- */
-#ifndef MOBILITY_MODEL_NOTIFIER_H
-#define MOBILITY_MODEL_NOTIFIER_H
-
-#include "ns3/object.h"
-#include "ns3/callback.h"
-#include "ns3/traced-callback.h"
-#include "mobility-model.h"
-
-namespace ns3 {
-
-/**
- * \brief notify listeners of position changes.
- */
-class MobilityModelNotifier : public Object
-{
-public:
-  static TypeId GetTypeId (void);
-
-  /**
-   * Create a new position notifier
-   */
-  MobilityModelNotifier ();
-
-  /**
-   * \param position the position which just changed.
-   */
-  void Notify (Ptr<const MobilityModel> position) const;
-private:
-  TracedCallback<Ptr<const MobilityModel> > m_trace;
-};
-
-} // namespace ns3
-
-#endif /* MOBILITY_MODEL_NOTIFIER_H */
--- a/src/mobility/mobility-model.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/mobility-model.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -17,9 +17,11 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
+
+#include <math.h>
+
 #include "mobility-model.h"
-#include "mobility-model-notifier.h"
-#include <math.h>
+#include "ns3/trace-source-accessor.h"
 
 namespace ns3 {
 
@@ -39,6 +41,9 @@
                    VectorValue (Vector (0.0, 0.0, 0.0)), // ignored initial value.
                    MakeVectorAccessor (&MobilityModel::GetVelocity),
                    MakeVectorChecker ())
+    .AddTraceSource ("CourseChange", 
+                     "The value of the position and/or velocity vector changed",
+                     MakeTraceSourceAccessor (&MobilityModel::m_courseChangeTrace))
     ;
   return tid;
 }
@@ -77,11 +82,7 @@
 void
 MobilityModel::NotifyCourseChange (void) const
 {
-  Ptr<MobilityModelNotifier> notifier = GetObject<MobilityModelNotifier> ();
-  if (notifier != 0)
-    {
-      notifier->Notify (this);
-    }
+  m_courseChangeTrace(this);
 }
 
 } // namespace ns3
--- a/src/mobility/mobility-model.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/mobility-model.h	Wed Jun 04 17:19:32 2008 -0400
@@ -20,8 +20,10 @@
 #ifndef MOBILITY_MODEL_H
 #define MOBILITY_MODEL_H
 
+#include "vector.h"
+
 #include "ns3/object.h"
-#include "vector.h"
+#include "ns3/traced-callback.h"
 
 namespace ns3 {
 
@@ -84,6 +86,13 @@
    * implement this method.
    */
   virtual Vector DoGetVelocity (void) const = 0;
+
+  /**
+   * Used to alert subscribers that a change in direction, velocity,
+   * or position has occurred.
+   */
+  TracedCallback<Ptr<const MobilityModel> > m_courseChangeTrace;
+
 };
 
 }; // namespace ns3
--- a/src/mobility/mobility.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/mobility.h	Wed Jun 04 17:19:32 2008 -0400
@@ -5,8 +5,8 @@
  *  - a set of mobility models which are used to track and maintain
  *    the "current" cartesian position and speed of an object.
  *
- *  - a "course change notifier" which can be used to register listeners
- *    to the course changes of a mobility model: ns3::MobilityModelNotifier.
+ *  - a "course change notifier" trace which can be used to register
+ *    listeners to the course changes of a mobility model
  *
  * The mobility models themselves are:
  *   - ns3::StaticMobilityModel: a model which maintains a constant position
--- a/src/mobility/random-walk-2d-mobility-model.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/random-walk-2d-mobility-model.h	Wed Jun 04 17:19:32 2008 -0400
@@ -37,8 +37,10 @@
  * Each instance moves with a speed and direction choosen at random
  * with the user-provided random variables until
  * either a fixed distance has been walked or until a fixed amount
- * of time.
- *
+ * of time. If we hit one of the boundaries (specified by a rectangle),
+ * of the model, we rebound on the boundary with a reflexive angle
+ * and speed. This model is often identified as a brownian motion
+ * model.
  */
 class RandomWalk2dMobilityModel : public MobilityModel 
 {
--- a/src/mobility/random-waypoint-mobility-model.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/random-waypoint-mobility-model.h	Wed Jun 04 17:19:32 2008 -0400
@@ -38,7 +38,8 @@
  *
  * The implementation of this model is not 2d-specific. i.e. if you provide
  * a 3d random waypoint position model to this mobility model, the model 
- * will still work.
+ * will still work. There is no 3d position allocator for now but it should
+ * be trivial to add one.
  */
 class RandomWaypointMobilityModel : public MobilityModel
 {
--- a/src/mobility/rectangle.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/rectangle.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -86,6 +86,7 @@
 Vector
 Rectangle::CalculateIntersection (const Vector &current, const Vector &speed) const
 {
+  NS_ASSERT (IsInside (current));
   double xMaxY = current.y + (this->xMax - current.x) / speed.x * speed.y;
   double xMinY = current.y + (this->xMin - current.x) / speed.x * speed.y;
   double yMaxX = current.x + (this->yMax - current.y) / speed.y * speed.x;
--- a/src/mobility/rectangle.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/rectangle.h	Wed Jun 04 17:19:32 2008 -0400
@@ -53,16 +53,43 @@
    * Create a zero-sized rectangle located at coordinates (0.0,0.0)
    */
   Rectangle ();
+  /**
+   * \param position the position to test.
+   * \returns true if the input position is located within the rectangle, 
+   *          false otherwise.
+   *
+   * This method compares only the x and y coordinates of the input position.
+   * It ignores the z coordinate.
+   */
   bool IsInside (const Vector &position) const;
+  /**
+   * \param position the position to test.
+   * \returns the side of the rectangle the input position is closest to.
+   *
+   * This method compares only the x and y coordinates of the input position.
+   * It ignores the z coordinate.
+   */
   Side GetClosestSide (const Vector &position) const;
+  /**
+   * \param current the current position
+   * \param speed the current speed
+   * \returns the intersection point between the rectangle and the current+speed vector.
+   *
+   * This method assumes that the current position is located _inside_
+   * the rectangle and checks for this with an assert.
+   * This method compares only the x and y coordinates of the input position
+   * and speed. It ignores the z coordinate.
+   */
   Vector CalculateIntersection (const Vector &current, const Vector &speed) const;
 
+  /* The x coordinate of the left bound of the rectangle */
   double xMin;
+  /* The x coordinate of the right bound of the rectangle */
   double xMax;
+  /* The y coordinate of the bottom bound of the rectangle */
   double yMin;
+  /* The y coordinate of the top bound of the rectangle */
   double yMax;
-
-  ATTRIBUTE_HELPER_HEADER_1 (Rectangle);
 };
 
 std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
@@ -73,7 +100,7 @@
  * \brief hold objects of type ns3::Rectangle
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Rectangle);
+ATTRIBUTE_HELPER_HEADER (Rectangle);
 
 } // namespace ns3
 
--- a/src/mobility/vector.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/vector.h	Wed Jun 04 17:19:32 2008 -0400
@@ -57,10 +57,13 @@
    * z coordinate of vector vector
    */
   double z;
-
-  ATTRIBUTE_HELPER_HEADER_1 (Vector);
 };
 
+/**
+ * \param a one point
+ * \param b another point
+ * \returns the cartesian distance between a and b.
+ */
 double CalculateDistance (const Vector &a, const Vector &b);
 
 /**
@@ -68,7 +71,7 @@
  * \brief hold objects of type ns3::Vector
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Vector);
+ATTRIBUTE_HELPER_HEADER (Vector);
 
 std::ostream &operator << (std::ostream &os, const Vector &vector);
 std::istream &operator >> (std::istream &is, Vector &vector);
--- a/src/mobility/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/mobility/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -6,7 +6,6 @@
         'vector.cc',
         'hierarchical-mobility-model.cc',
         'mobility-model.cc',
-        'mobility-model-notifier.cc',
         'position-allocator.cc',
         'rectangle.cc',
         'static-mobility-model.cc',
@@ -23,7 +22,6 @@
         'vector.h',
         'hierarchical-mobility-model.h',
         'mobility-model.h',
-        'mobility-model-notifier.h',
         'position-allocator.h',
         'rectangle.h',
         'static-mobility-model.h',
--- a/src/node/address-utils.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/address-utils.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -23,7 +23,7 @@
 
 void WriteTo (Buffer::Iterator &i, Ipv4Address ad)
 {
-  i.WriteHtonU32 (ad.GetHostOrder ());
+  i.WriteHtonU32 (ad.Get ());
 }
 void WriteTo (Buffer::Iterator &i, const Address &ad)
 {
@@ -40,7 +40,7 @@
 
 void ReadFrom (Buffer::Iterator &i, Ipv4Address &ad)
 {
-  ad.SetHostOrder (i.ReadNtohU32 ());
+  ad.Set (i.ReadNtohU32 ());
 }
 void ReadFrom (Buffer::Iterator &i, Address &ad, uint32_t len)
 {
--- a/src/node/address.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/address.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -107,6 +107,29 @@
   return type;
 }
 
+uint32_t
+Address::GetSerializedSize (void) const
+{
+  return 1 + 1 + m_len;
+}
+
+void
+Address::Serialize (TagBuffer buffer) const
+{
+  buffer.WriteU8 (m_type);
+  buffer.WriteU8 (m_len);
+  buffer.Write (m_data,  m_len);
+}
+
+void
+Address::Deserialize (TagBuffer buffer)
+{
+  m_type = buffer.ReadU8 ();
+  m_len = buffer.ReadU8 ();
+  NS_ASSERT (m_len <= MAX_SIZE);
+  buffer.Read (m_data, m_len);
+}
+
 ATTRIBUTE_HELPER_CPP (Address);
 
 
@@ -139,8 +162,14 @@
 }
 bool operator < (const Address &a, const Address &b)
 {
-  // XXX: it is not clear to me how to order based on type.
-  // so, we do not compare the types here but we should.
+  if (a.m_type < b.m_type)
+    {
+      return true;
+    }
+  else if (a.m_type > b.m_type)
+    {
+      return false;
+    }
   if (a.m_len < b.m_len)
     {
       return true;
--- a/src/node/address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -5,10 +5,16 @@
 #include <ostream>
 #include "ns3/attribute.h"
 #include "ns3/attribute-helper.h"
+#include "ns3/tag-buffer.h"
 
 namespace ns3 {
 
 /**
+ * \ingroup node
+ * \defgroup address Address
+ */
+/**
+ * \ingroup address
  * \brief a polymophic address class
  *
  * This class is very similar in design and spirit to the BSD sockaddr
@@ -153,8 +159,26 @@
    * \returns a new type id.
    */
   static uint8_t Register (void);
+  /**
+   * Get the number of bytes needed to serialize the underlying Address
+   * Typically, this is GetLength () + 2 
+   *
+   * \returns the number of bytes required for an Address in serialized form
+   */
+  uint32_t GetSerializedSize (void) const;
+  /**
+   * Serialize this address in host byte order to a byte buffer
+   *
+   * \param buffer output buffer that gets written with this Address
+   */
+  void Serialize (TagBuffer buffer) const;
+  /**
+   * \param buffer buffer to read address from
+   * 
+   * The input address buffer is expected to be in host byte order format.
+   */
+  void Deserialize (TagBuffer buffer);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Address);
 private:
   friend bool operator == (const Address &a, const Address &b);
   friend bool operator < (const Address &a, const Address &b);
@@ -171,7 +195,7 @@
  * \brief hold objects of type ns3::Address
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Address);
+ATTRIBUTE_HELPER_HEADER (Address);
 
 bool operator == (const Address &a, const Address &b);
 bool operator != (const Address &a, const Address &b);
--- a/src/node/application.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/application.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -108,15 +108,13 @@
 // Private helpers
 void Application::ScheduleStart (const Time &startTime)
 {
-  m_startEvent = Simulator::Schedule(startTime -
-                                     Simulator::Now(),
-                                     &Application::StartApplication, this);
+  m_startEvent = Simulator::Schedule (startTime,
+                                      &Application::StartApplication, this);
 }
 
 void Application::ScheduleStop (const Time &stopTime)
 {
-  m_stopEvent = Simulator::Schedule(stopTime -
-                                    Simulator::Now(),
+  m_stopEvent = Simulator::Schedule (stopTime,
                                     &Application::StopApplication, this);
 }
 
--- a/src/node/application.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/application.h	Wed Jun 04 17:19:32 2008 -0400
@@ -33,7 +33,12 @@
 class RandomVariable;
 
 /**
- * \brief The base class for all ns3 applicationes
+ * \ingroup node
+ * \defgroup application Application
+ */
+/**
+ * \ingroup application
+ * \brief The base class for all ns3 applications
  * 
  * Class Application is the base class for all ns3 applications.
  * Applications are associated with individual nodes.
@@ -53,13 +58,13 @@
 {
 public:
   static TypeId GetTypeId (void);
-  Application();
-  virtual ~Application();
+  Application ();
+  virtual ~Application ();
   
   /**
    * \brief Specify application start time
-   * \param startTime Start time for this application, absolute time,
-   *        relative to the start of the simulation.
+   * \param startTime Start time for this application,
+   *        relative to the current simulation time.
    *
    * Applications start at various times in the simulation scenario.
    * The Start method specifies when the application should be
@@ -67,20 +72,20 @@
    * private "StartApplication" method defined below, which is called at the
    * time specified, to cause the application to begin.
    */
-  void Start(const Time& startTime);
+  void Start (const Time& startTime);
 
   /** 
    * \brief Specify application start time.
    * \param startVariable the random variable to use to pick
-   *        the real start time as an absolute time, in units of
-   *        seconds, relative to the start of the simulation.
+   *        the real start time as a relative time, in units of
+   *        seconds, relative to the current simulation time.
    */
-  void Start(const RandomVariable& startVariable);
+  void Start (const RandomVariable& startVariable);
   
   /**
    * \brief Specify application stop time
    * \param stopTime Stop time for this application, relative to the
-   *        start of the simulation.
+   *        current simulation time.
    *
    * Once an application has started, it is sometimes useful
    * to stop the application.  The Stop method specifies when an
@@ -88,20 +93,20 @@
    * the private StopApplication method, to be notified when that
    * time has come.
    */
-  void Stop(const Time& stopTime);
+  void Stop (const Time& stopTime);
 
   /**
    * \brief Specify application stop time
    * \param stopVariable the random variable to use to pick
    *        the real stop time, in units of seconds, 
-   *        relative to the start of the simulation.
+   *        relative to the current simulation time.
    */
-  void Stop(const RandomVariable& stopVariable);
+  void Stop (const RandomVariable& stopVariable);
 
   /**
    * \returns the Node to which this Application object is attached.
    */
-  Ptr<Node> GetNode() const;
+  Ptr<Node> GetNode () const;
 
   /**
    * \param node the node to which this Application object is attached.
--- a/src/node/channel.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/channel.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,11 @@
 class NetDevice;
 
 /**
+ * \ingroup node
+ * \defgroup channel Channel
+ */
+/**
+ * \ingroup channel
  * \brief Abstract Channel Base Class.
  *
  * A channel is a logical path over which information flows.  The path can
--- a/src/node/drop-tail-queue.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/drop-tail-queue.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,8 @@
 class TraceContainer;
 
 /**
+ * \ingroup queue
+ *
  * \brief A FIFO packet queue that drops tail-end packets on overflow
  */
 class DropTailQueue : public Queue {
--- a/src/node/ethernet-header.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ethernet-header.h	Wed Jun 04 17:19:32 2008 -0400
@@ -38,6 +38,8 @@
     QINQ      /**< Double tagged packet. Header includes two VLAN tags */
   };
 /**
+ * \ingroup node
+ *
  * \brief Packet header for Ethernet
  *
  * This class can be used to add a header to an ethernet packet that
--- a/src/node/ethernet-trailer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ethernet-trailer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 class Packet;
 
 /**
+ * \ingroup node
+ *
  * \brief Packet trailer for Ethernet
  *
  * This class can be used to add and verify the FCS at the end of an
--- a/src/node/inet-socket-address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/inet-socket-address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,8 @@
 
 
 /**
+ * \ingroup address
+ *
  * \brief an Inet address class
  *
  * This class is similar to inet_sockaddr in the BSD socket
--- a/src/node/ipv4-address-generator.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4-address-generator.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -137,9 +137,9 @@
 // We're going to be playing with the actual bits in the network and mask so
 // pull them out into ints.
 //
-  uint32_t maskBits __attribute__((unused)) = mask.GetHostOrder ();
-  uint32_t netBits = net.GetHostOrder ();
-  uint32_t addrBits = addr.GetHostOrder ();
+  uint32_t maskBits __attribute__((unused)) = mask.Get ();
+  uint32_t netBits = net.Get ();
+  uint32_t addrBits = addr.Get ();
 //
 // Some quick reasonableness testing.
 //
@@ -203,7 +203,7 @@
   NS_LOG_FUNCTION_NOARGS ();
 
   uint32_t index = MaskToIndex (mask);
-  uint32_t addrBits = addr.GetHostOrder ();
+  uint32_t addrBits = addr.Get ();
 
   NS_ASSERT_MSG (addrBits <= m_netTable[index].addrMax,
     "Ipv4AddressGeneratorImpl::InitAddress(): Address overflow");
@@ -258,7 +258,7 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
 
-  uint32_t addr = address.GetHostOrder ();
+  uint32_t addr = address.Get ();
 
   NS_ASSERT_MSG (addr, "Ipv4AddressGeneratorImpl::Add(): "
     "Allocating the broadcast address is not a good idea"); 
@@ -367,7 +367,7 @@
 // We use the number of bits in the mask as the number of bits in the network
 // number and as the index into the network number state table.
 //
-  uint32_t maskBits = mask.GetHostOrder ();
+  uint32_t maskBits = mask.Get ();
 
   for (uint32_t i = 0; i < N_BITS; ++i)
     {
--- a/src/node/ipv4-address-generator.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4-address-generator.h	Wed Jun 04 17:19:32 2008 -0400
@@ -23,6 +23,12 @@
 
 namespace ns3 {
 
+/**
+ * \ingroup address
+ *
+ * \brief This generator assigns addresses sequentially from a provided
+ * network address; used in topology code.
+ */
 class Ipv4AddressGenerator {
 public:
   static void Init (const Ipv4Address net, const Ipv4Mask mask, 
--- a/src/node/ipv4-address.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4-address.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -81,7 +81,7 @@
 bool 
 Ipv4Mask::IsMatch (Ipv4Address a, Ipv4Address b) const
 {
-  if ((a.GetHostOrder () & m_mask) == (b.GetHostOrder () & m_mask)) {
+  if ((a.Get () & m_mask) == (b.Get () & m_mask)) {
     return true;
   } else {
     return false;
@@ -89,14 +89,14 @@
 }
 
 uint32_t 
-Ipv4Mask::GetHostOrder (void) const
+Ipv4Mask::Get (void) const
 {
   return m_mask;
 }
 void 
-Ipv4Mask::SetHostOrder (uint32_t value)
+Ipv4Mask::Set (uint32_t mask)
 {
-  m_mask = value;
+  m_mask = mask;
 }
 uint32_t 
 Ipv4Mask::GetInverse (void) const
@@ -139,6 +139,11 @@
   m_address = AsciiToIpv4Host (address);
 }
 
+uint32_t
+Ipv4Address::Get (void) const
+{
+  return m_address;
+}
 void
 Ipv4Address::Set (uint32_t address)
 {
@@ -153,19 +158,19 @@
 Ipv4Address
 Ipv4Address::CombineMask (Ipv4Mask const &mask) const
 {
-  return Ipv4Address (GetHostOrder () & mask.GetHostOrder ());
+  return Ipv4Address (Get () & mask.Get ());
 }
 
 Ipv4Address 
 Ipv4Address::GetSubnetDirectedBroadcast (Ipv4Mask const &mask) const
 {
-  return Ipv4Address (GetHostOrder () | mask.GetInverse ());
+  return Ipv4Address (Get () | mask.GetInverse ());
 }
 
 bool
 Ipv4Address::IsSubnetDirectedBroadcast (Ipv4Mask const &mask) const
 {
-  return ( (GetHostOrder () | mask.GetInverse ()) == GetHostOrder () );
+  return ( (Get () | mask.GetInverse ()) == Get () );
 }
 
 bool
@@ -184,16 +189,6 @@
   return (m_address >= 0xe0000000 && m_address <= 0xefffffff);
 }
 
-uint32_t
-Ipv4Address::GetHostOrder (void) const
-{
-  return m_address;
-}
-void 
-Ipv4Address::SetHostOrder (uint32_t ip)
-{
-  m_address = ip;
-}
 void
 Ipv4Address::Serialize (uint8_t buf[4]) const
 {
@@ -287,7 +282,7 @@
 
 size_t Ipv4AddressHash::operator()(Ipv4Address const &x) const 
 { 
-  return x.GetHostOrder ();
+  return x.Get ();
 }
 
 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address)
--- a/src/node/ipv4-address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4-address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,9 +30,11 @@
 
 class Ipv4Mask;
 
-/** Ipv4 addresses are stored in host order in
-  * this class.
-  */
+/** 
+ * \ingroup address
+ *
+ * \brief Ipv4 addresses are stored in host order in this class.
+ */
 class Ipv4Address {
 public:
   Ipv4Address ();
@@ -51,7 +53,11 @@
     * \param address C-string containing the address as described above
     */
   Ipv4Address (char const *address);
-  
+  /** 
+   * Get the host-order 32-bit IP address
+   * \return the host-order 32-bit IP address
+   */
+  uint32_t Get (void) const;
   /**
    * input address is in host order.
    * \param address The host order 32-bit address
@@ -67,7 +73,6 @@
     * \param address C-string containing the address as described above
     */
   void Set (char const *address);
-
   /**
    * \brief Comparison operation between two Ipv4Addresses
    * \param other address to which to compare this address
@@ -77,17 +82,6 @@
   {
     return m_address == other.m_address;
   }
-
-  /** 
-   * \brief Get the host-order 32-bit IP address
-   *
-   * Using this method is frowned upon.
-   * Please, do _not_ use this method.
-   * It is there only for chunk-ipv4.
-   * \return the host-order 32-bit IP address
-   */
-  uint32_t GetHostOrder (void) const;
-  void SetHostOrder (uint32_t ip);
   /**
    * Serialize this address to a 4-byte buffer
    *
@@ -142,7 +136,6 @@
   static Ipv4Address GetBroadcast (void);
   static Ipv4Address GetLoopback (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ipv4Address);
 private:
   Address ConvertTo (void) const;
   static uint8_t GetType (void);
@@ -153,7 +146,11 @@
   friend bool operator < (Ipv4Address const &addrA, Ipv4Address const &addrB);
 };
 
-
+/**
+ * \ingroup address
+ *
+ * \brief a class to represent an Ipv4 address mask
+ */
 class Ipv4Mask {
 public:
   Ipv4Mask ();
@@ -163,13 +160,16 @@
   bool IsMatch (Ipv4Address a, Ipv4Address b) const;
 
   bool IsEqual (Ipv4Mask other) const;
-
-
-  /* Using this method is frowned upon.
-   * Please, do _not_ use this method.
+  /** 
+   * Get the host-order 32-bit IP mask
+   * \return the host-order 32-bit IP mask
    */
-  uint32_t GetHostOrder (void) const;
-  void SetHostOrder (uint32_t value);
+  uint32_t Get (void) const;
+  /**
+   * input mask is in host order.
+   * \param mask The host order 32-bit mask
+   */
+  void Set (uint32_t mask);
   /**
    * \brief Return the inverse mask in host order. 
    */
@@ -180,7 +180,6 @@
   static Ipv4Mask GetLoopback (void);
   static Ipv4Mask GetZero (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Ipv4Mask);
 private:
   uint32_t m_mask;
 };
@@ -194,8 +193,8 @@
  * \brief hold objects of type ns3::Ipv4Mask
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Ipv4Address);
-ATTRIBUTE_HELPER_HEADER_2 (Ipv4Mask);
+ATTRIBUTE_HELPER_HEADER (Ipv4Address);
+ATTRIBUTE_HELPER_HEADER (Ipv4Mask);
 
 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
 std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-header.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,332 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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/assert.h"
+#include "ns3/log.h"
+#include "ns3/header.h"
+#include "ipv4-header.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4Header");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ipv4Header);
+
+bool Ipv4Header::m_calcChecksum = false;
+
+Ipv4Header::Ipv4Header ()
+  : m_payloadSize (0),
+    m_identification (0),
+    m_tos (0),
+    m_ttl (0),
+    m_protocol (0),
+    m_flags (0),
+    m_fragmentOffset (0),
+    m_goodChecksum (true)
+{}
+
+void 
+Ipv4Header::EnableChecksums (void)
+{
+  m_calcChecksum = true;
+}
+
+void 
+Ipv4Header::SetPayloadSize (uint16_t size)
+{
+  m_payloadSize = size;
+}
+uint16_t 
+Ipv4Header::GetPayloadSize (void) const
+{
+  return m_payloadSize;
+}
+
+uint16_t 
+Ipv4Header::GetIdentification (void) const
+{
+  return m_identification;
+}
+void 
+Ipv4Header::SetIdentification (uint16_t identification)
+{
+  m_identification = identification;
+}
+
+
+
+void 
+Ipv4Header::SetTos (uint8_t tos)
+{
+  m_tos = tos;
+}
+uint8_t 
+Ipv4Header::GetTos (void) const
+{
+  return m_tos;
+}
+void 
+Ipv4Header::SetMoreFragments (void)
+{
+  m_flags |= MORE_FRAGMENTS;
+}
+void
+Ipv4Header::SetLastFragment (void)
+{
+  m_flags &= ~MORE_FRAGMENTS;
+}
+bool 
+Ipv4Header::IsLastFragment (void) const
+{
+  return !(m_flags & MORE_FRAGMENTS);
+}
+
+void 
+Ipv4Header::SetDontFragment (void)
+{
+  m_flags |= DONT_FRAGMENT;
+}
+void 
+Ipv4Header::SetMayFragment (void)
+{
+  m_flags &= ~DONT_FRAGMENT;
+}
+bool 
+Ipv4Header::IsDontFragment (void) const
+{
+  return (m_flags & DONT_FRAGMENT);
+}
+
+void 
+Ipv4Header::SetFragmentOffset (uint16_t offset)
+{
+  NS_ASSERT (!(offset & (~0x3fff)));
+  m_fragmentOffset = offset;
+}
+uint16_t 
+Ipv4Header::GetFragmentOffset (void) const
+{
+  NS_ASSERT (!(m_fragmentOffset & (~0x3fff)));
+  return m_fragmentOffset;
+}
+
+void 
+Ipv4Header::SetTtl (uint8_t ttl)
+{
+  m_ttl = ttl;
+}
+uint8_t 
+Ipv4Header::GetTtl (void) const
+{
+  return m_ttl;
+}
+  
+uint8_t 
+Ipv4Header::GetProtocol (void) const
+{
+  return m_protocol;
+}
+void 
+Ipv4Header::SetProtocol (uint8_t protocol)
+{
+  m_protocol = protocol;
+}
+
+void 
+Ipv4Header::SetSource (Ipv4Address source)
+{
+  m_source = source;
+}
+Ipv4Address
+Ipv4Header::GetSource (void) const
+{
+  return m_source;
+}
+
+void 
+Ipv4Header::SetDestination (Ipv4Address dst)
+{
+  m_destination = dst;
+}
+Ipv4Address
+Ipv4Header::GetDestination (void) const
+{
+  return m_destination;
+}
+
+
+bool
+Ipv4Header::IsChecksumOk (void) const
+{
+  return m_goodChecksum;
+}
+
+
+TypeId 
+Ipv4Header::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4Header")
+    .SetParent<Header> ()
+    .AddConstructor<Ipv4Header> ()
+    ;
+  return tid;
+}
+TypeId 
+Ipv4Header::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+void 
+Ipv4Header::Print (std::ostream &os) const
+{
+  // ipv4, right ?
+  std::string flags;
+  if (m_flags == 0)
+    {
+      flags = "none";
+    }
+  else if (m_flags & MORE_FRAGMENTS &&
+           m_flags & DONT_FRAGMENT)
+    {
+      flags = "MF|DF";
+    }
+  else if (m_flags & DONT_FRAGMENT)
+    {
+      flags = "DF";
+    }
+  else if (m_flags & MORE_FRAGMENTS)
+    {
+      flags = "MF";
+    }
+  else
+    {
+      flags = "XX";
+    }
+  os << "tos 0x" << std::hex << m_tos << std::dec << " "
+     << "ttl " << m_ttl << " "
+     << "id " << m_identification << " "
+     << "offset " << m_fragmentOffset << " "
+     << "flags [" << flags << "] "
+     << "length: " << (m_payloadSize + 5 * 4)
+     << " " 
+     << m_source << " > " << m_destination
+    ;
+}
+uint32_t 
+Ipv4Header::GetSerializedSize (void) const
+{
+  return 5 * 4;
+}
+
+void
+Ipv4Header::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  
+  uint8_t verIhl = (4 << 4) | (5);
+  i.WriteU8 (verIhl);
+  i.WriteU8 (m_tos);
+  i.WriteHtonU16 (m_payloadSize + 5*4);
+  i.WriteHtonU16 (m_identification);
+  uint32_t fragmentOffset = m_fragmentOffset / 8;
+  uint8_t flagsFrag = (fragmentOffset >> 8) & 0x1f;
+  if (m_flags & DONT_FRAGMENT) 
+    {
+      flagsFrag |= (1<<6);
+    }
+  if (m_flags & MORE_FRAGMENTS) 
+    {
+      flagsFrag |= (1<<5);
+    }
+  i.WriteU8 (flagsFrag);
+  uint8_t frag = fragmentOffset & 0xff;
+  i.WriteU8 (frag);
+  i.WriteU8 (m_ttl);
+  i.WriteU8 (m_protocol);
+  i.WriteHtonU16 (0);
+  i.WriteHtonU32 (m_source.Get ());
+  i.WriteHtonU32 (m_destination.Get ());
+
+  if (m_calcChecksum) 
+    {
+#if 0
+      // XXX we need to add Buffer::Iterator::PeekData method
+      uint8_t *data = start.PeekData ();
+      uint16_t checksum = UtilsChecksumCalculate (0, data, GetSize ());
+      checksum = UtilsChecksumComplete (checksum);
+      NS_LOG_LOGIC ("checksum=" <<checksum);
+      i = start;
+      i.Next (10);
+      i.WriteU16 (checksum);
+#endif
+    }
+}
+uint32_t
+Ipv4Header::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t verIhl = i.ReadU8 ();
+  uint8_t ihl = verIhl & 0x0f; 
+  uint16_t headerSize = ihl * 4;
+  NS_ASSERT ((verIhl >> 4) == 4);
+  m_tos = i.ReadU8 ();
+  uint16_t size = i.ReadNtohU16 ();
+  m_payloadSize = size - headerSize;
+  m_identification = i.ReadNtohU16 ();
+  uint8_t flags = i.ReadU8 ();
+  m_flags = 0;
+  if (flags & (1<<6)) 
+    {
+      m_flags |= DONT_FRAGMENT;
+    }
+  if (flags & (1<<5)) 
+    {
+      m_flags |= MORE_FRAGMENTS;
+    }
+  i.Prev ();
+  m_fragmentOffset = i.ReadU8 () & 0x1f;
+  m_fragmentOffset <<= 8;
+  m_fragmentOffset |= i.ReadU8 ();
+  m_fragmentOffset <<= 3;
+  m_ttl = i.ReadU8 ();
+  m_protocol = i.ReadU8 ();
+  i.Next (2); // checksum
+  m_source.Set (i.ReadNtohU32 ());
+  m_destination.Set (i.ReadNtohU32 ());
+
+  if (m_calcChecksum) 
+    {
+#if 0
+      uint8_t *data = start.PeekData ();
+      uint16_t localChecksum = UtilsChecksumCalculate (0, data, headerSize);
+      if (localChecksum == 0xffff) 
+        {
+          m_goodChecksum = true;
+        } 
+      else 
+        {
+          m_goodChecksum = false;
+        }
+#endif
+    }
+  return GetSerializedSize ();
+}
+
+}; // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/ipv4-header.h	Wed Jun 04 17:19:32 2008 -0400
@@ -0,0 +1,171 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005 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>
+ */
+
+#ifndef IPV4_HEADER_H
+#define IPV4_HEADER_H
+
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+
+namespace ns3 {
+/**
+ * \brief Packet header for IPv4
+ */
+class Ipv4Header : public Header 
+{
+public:
+  /**
+   * \brief Construct a null IPv4 header
+   */
+  Ipv4Header ();
+  /**
+   * \brief Enable checksum calculation for IP (XXX currently has no effect)
+   */
+  static void EnableChecksums (void);
+  /**
+   * \param size the size of the payload in bytes
+   */
+  void SetPayloadSize (uint16_t size);
+  /**
+   * \param identification the Identification field of IPv4 packets.
+   *
+   * By default, set to zero.
+   */
+  void SetIdentification (uint16_t identification);
+  /**
+   * \param tos the 8 bits of Ipv4 TOS.
+   */
+  void SetTos (uint8_t tos);
+  /**
+   * This packet is not the last packet of a fragmented ipv4 packet.
+   */
+  void SetMoreFragments (void);
+  /**
+   * This packet is the last packet of a fragmented ipv4 packet.
+   */
+  void SetLastFragment (void);
+  /**
+   * Don't fragment this packet: if you need to anyway, drop it.
+   */
+  void SetDontFragment (void);
+  /**
+   * If you need to fragment this packet, you can do it.
+   */
+  void SetMayFragment (void);
+  /**
+   * \param offset the ipv4 fragment offset
+   */
+  void SetFragmentOffset (uint16_t offset);
+  /**
+   * \param ttl the ipv4 TTL
+   */
+  void SetTtl (uint8_t ttl);
+  /**
+   * \param num the ipv4 protocol field
+   */
+  void SetProtocol (uint8_t num);
+  /**
+   * \param source the source of this packet
+   */
+  void SetSource (Ipv4Address source);
+  /**
+   * \param destination the destination of this packet.
+   */
+  void SetDestination (Ipv4Address destination);
+  /**
+   * \returns the size of the payload in bytes
+   */
+  uint16_t GetPayloadSize (void) const;
+  /**
+   * \returns the identification field of this packet.
+   */
+  uint16_t GetIdentification (void) const;
+  /**
+   * \returns the TOS field of this packet.
+   */
+  uint8_t GetTos (void) const;
+  /**
+   * \returns true if this is the last fragment of a packet, false otherwise.
+   */
+  bool IsLastFragment (void) const;
+  /**
+   * \returns true if this is this packet can be fragmented.
+   */  
+  bool IsDontFragment (void) const;
+  /**
+   * \returns the offset of this fragment.
+   */
+  uint16_t GetFragmentOffset (void) const;
+  /**
+   * \returns the TTL field of this packet
+   */
+  uint8_t GetTtl (void) const;
+  /**
+   * \returns the protocol field of this packet
+   */
+  uint8_t GetProtocol (void) const;
+  /**
+   * \returns the source address of this packet
+   */
+  Ipv4Address GetSource (void) const;
+  /**
+   * \returns the destination address of this packet
+   */
+  Ipv4Address GetDestination (void) const;
+  
+  /**
+   * \returns true if the upv4 checksum is correct, false otherwise.
+   *
+   * If Ipv4Header::EnableChecksums has not been called prior to
+   * creating this packet, this method will always return true.
+   */
+  bool IsChecksumOk (void) const;
+
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual void Print (std::ostream &os) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (Buffer::Iterator start) const;
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+private:
+
+  enum FlagsE {
+    DONT_FRAGMENT = (1<<0),
+    MORE_FRAGMENTS = (1<<1)
+  };
+
+  static bool m_calcChecksum;
+
+  uint16_t m_payloadSize;
+  uint16_t m_identification;
+  uint32_t m_tos : 8;
+  uint32_t m_ttl : 8;
+  uint32_t m_protocol : 8;
+  uint32_t m_flags : 3;
+  uint16_t m_fragmentOffset : 13;
+  Ipv4Address m_source;
+  Ipv4Address m_destination;
+  bool m_goodChecksum;
+};
+
+} // namespace ns3
+
+
+#endif /* IPV4_HEADER_H */
--- a/src/node/ipv4-route.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4-route.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,7 @@
 
 namespace ns3 {
 /**
+ * \ingroup ipv4
  * \brief A record of an IPv4 route
  */
 class Ipv4Route {
@@ -106,6 +107,7 @@
 std::ostream& operator<< (std::ostream& os, Ipv4Route const& route);
 
 /**
+ * \ingroup ipv4 
  * \brief A record of an IPv4 multicast route
  */
 class Ipv4MulticastRoute {
--- a/src/node/ipv4.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/ipv4.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,10 +32,16 @@
 class NetDevice;
 class Packet;
 class Ipv4Route;
-class Ipv4Header; // FIXME: ipv4-header.h needs to move from module
-                  // "internet-node" to module "node"
+class Ipv4Header;
 
 /**
+ * \ingroup node
+ * \defgroup ipv4 Ipv4
+ */
+
+/**
+ * \ingroup ipv4
+ *
  * \brief Base class for IPv4 routing protocols.
  *
  * This class represents the interface between the IPv4 routing core
--- a/src/node/llc-snap-header.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/llc-snap-header.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,11 @@
 
 namespace ns3 {
 
+/**
+ * \ingroup node
+ *
+ * \brief Header for the LLC/SNAP encapsulation
+ */
 class LlcSnapHeader : public Header 
 {
 public:
--- a/src/node/mac48-address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/mac48-address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,8 @@
 class Address;
 
 /**
+ * \ingroup address
+ * 
  * \brief an EUI-48 address
  *
  * This class can contain 48 bit IEEE addresses.
@@ -96,7 +98,6 @@
    */
   static Mac48Address GetBroadcast (void);
 
-  ATTRIBUTE_HELPER_HEADER_1 (Mac48Address);
 private:
   /**
    * \returns a new Address instance
@@ -117,7 +118,7 @@
  * \brief hold objects of type ns3::Mac48Address
  */
 
-ATTRIBUTE_HELPER_HEADER_2 (Mac48Address);
+ATTRIBUTE_HELPER_HEADER (Mac48Address);
 
 bool operator == (const Mac48Address &a, const Mac48Address &b);
 bool operator != (const Mac48Address &a, const Mac48Address &b);
--- a/src/node/mac64-address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/mac64-address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,8 @@
 class Address;
 
 /**
+ * \ingroup address
+ *
  * \brief an EUI-64 address
  *
  * This class can contain 64 bit IEEE addresses.
--- a/src/node/net-device.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/net-device.h	Wed Jun 04 17:19:32 2008 -0400
@@ -32,11 +32,16 @@
 namespace ns3 {
 
 class Node;
-class TraceContext;
 class Channel;
 class Packet;
 
 /**
+ * \ingroup node
+ * \defgroup netdevice NetDevice
+ */
+/**
+ * \ingroup netdevice
+ *
  * \brief Network layer to device interface
  *
  * This interface defines the API which the IP and ARP
--- a/src/node/node-list.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/node-list.h	Wed Jun 04 17:19:32 2008 -0400
@@ -31,6 +31,8 @@
 
 
 /**
+ * \ingroup node
+ *
  * \brief the list of simulation nodes.
  *
  * Every Node created is automatically added to this list.
--- a/src/node/node.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/node.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,7 +29,6 @@
 
 namespace ns3 {
 
-class TraceContext;
 class NetDevice;
 class Application;
 class Packet;
@@ -37,6 +36,8 @@
 
 
 /**
+ * \ingroup node
+ *
  * \brief A network Node.
  *
  * This class holds together:
@@ -169,9 +170,6 @@
    * \param device the device added to this Node.
    *
    * This method is invoked whenever a user calls Node::AddDevice.
-   * Subclasses are expected to call NetDevice::SetReceiveCallback
-   * at this point to setup the node's receive function for
-   * the NetDevice packets.
    */
   virtual void NotifyDeviceAdded (Ptr<NetDevice> device);
 
--- a/src/node/packet-socket-address.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/packet-socket-address.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,11 @@
 
 class NetDevice;
 
+/**
+ * \ingroup address
+ *
+ * \brief an address for a packet socket
+ */
 class PacketSocketAddress
 {
  public:
--- a/src/node/packet-socket-factory.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/packet-socket-factory.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 class Socket;
 
 /**
+ * \ingroup socket 
+ * 
  * This can be used as an interface in a node in order for the node to
  * generate PacketSockets that can connect to net devices.
  */
--- a/src/node/packet-socket.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/packet-socket.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 #include "ns3/uinteger.h"
 #include "ns3/trace-source-accessor.h"
 
+#include <algorithm>
+
 NS_LOG_COMPONENT_DEFINE ("PacketSocket");
 
 namespace ns3 {
@@ -220,6 +222,12 @@
   NotifyConnectionFailed ();
   return -1;
 }
+int 
+PacketSocket::Listen(uint32_t queueLimit)
+{
+  m_errno = Socket::ERROR_OPNOTSUPP;
+  return -1;
+}
 
 int
 PacketSocket::Send (Ptr<Packet> p)
@@ -234,11 +242,35 @@
   return SendTo (p, m_destAddr);
 }
 
-// XXX must limit it to interface MTU
+uint32_t
+PacketSocket::GetMinMtu (PacketSocketAddress ad) const
+{
+  if (ad.IsSingleDevice ())
+    {
+      Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
+      return device->GetMtu ();
+    }
+  else
+    {
+      uint32_t minMtu = 0xffff;
+      for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
+        {
+          Ptr<NetDevice> device = m_node->GetDevice (i);
+          minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
+        }
+      return minMtu;
+    }
+}
+
 uint32_t 
 PacketSocket::GetTxAvailable (void) const
 {
-  // Use 65536 for now
+  if (m_state == STATE_CONNECTED)
+    {
+      PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (m_destAddr);      
+      return GetMinMtu (ad);
+    }
+  // If we are not connected, we return a 'safe' value by default.
   return 0xffff;
 }
 
@@ -253,13 +285,6 @@
       m_errno = ERROR_BADF;
       return -1;
     }
-  if (m_state == STATE_OPEN)
-    {
-      // XXX should return another error here.
-      NS_LOG_LOGIC ("ERROR_INVAL");
-      m_errno = ERROR_INVAL;
-      return -1;
-    }
   if (m_shutdownSend)
     {
       NS_LOG_LOGIC ("ERROR_SHUTDOWN");
@@ -272,12 +297,12 @@
       m_errno = ERROR_AFNOSUPPORT;
       return -1;
     }
-  if (p->GetSize () > GetTxAvailable ())
+  ad = PacketSocketAddress::ConvertFrom (address);
+  if (p->GetSize () > GetMinMtu (ad))
     {
       m_errno = ERROR_MSGSIZE;
       return -1;
     }
-  ad = PacketSocketAddress::ConvertFrom (address);
   
   bool error = false;
   Address dest = ad.GetPhysicalAddress ();
--- a/src/node/packet-socket.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/packet-socket.h	Wed Jun 04 17:19:32 2008 -0400
@@ -36,6 +36,8 @@
 class PacketSocketAddress;
 
 /**
+ * \ingroup socket
+ *
  * \brief A PacketSocket is a link between an application and a net device.
  *
  * A PacketSocket can be used to connect an application to a net
@@ -69,6 +71,8 @@
  *       The fields "physical address", device, and protocol are filled.
  *
  * - Accept: not allowed
+ *
+ * - Listen: returns -1 (OPNOTSUPP)
  */
 class PacketSocket : public Socket
 {
@@ -88,6 +92,7 @@
   virtual int ShutdownSend (void);
   virtual int ShutdownRecv (void);
   virtual int Connect(const Address &address);
+  virtual int Listen(uint32_t queueLimit);
   virtual int Send (Ptr<Packet> p);
   virtual uint32_t GetTxAvailable (void) const;
 
@@ -100,6 +105,7 @@
   void ForwardUp (Ptr<NetDevice> device, Ptr<Packet> packet, 
                   uint16_t protocol, const Address &from);
   int DoBind (const PacketSocketAddress &address);
+  uint32_t GetMinMtu (PacketSocketAddress ad) const;
   virtual void DoDispose (void);
 
   enum State {
--- a/src/node/queue.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/queue.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -100,8 +100,11 @@
 void
 Queue::DequeueAll (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
-  NS_ASSERT_MSG (0, "Don't know what to do with dequeued packets!");
+  NS_LOG_FUNCTION (this);
+  while (!IsEmpty ())
+    {
+      Dequeue ();
+    }
 }
 
 Ptr<Packet>
--- a/src/node/queue.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/queue.h	Wed Jun 04 17:19:32 2008 -0400
@@ -33,6 +33,11 @@
 namespace ns3 {
 
 /**
+ * \ingroup node
+ * \defgroup queue Queue
+ */
+/**
+ * \ingroup queue
  * \brief Abstract base class for packet Queues
  * 
  * This class defines the base APIs for packet queues in the ns-3 system
@@ -66,7 +71,7 @@
   Ptr<Packet> Peek (void) const;
 
   /**
-   * XXX Doesn't do anything right now, think its supposed to flush the queue
+   * Flush the queue.
    */
   void DequeueAll (void);
   /**
--- a/src/node/simple-channel.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/simple-channel.h	Wed Jun 04 17:19:32 2008 -0400
@@ -10,6 +10,10 @@
 class SimpleNetDevice;
 class Packet;
 
+/**
+ * \ingroup channel
+ * \brief A simple channel, for simple things and testing
+ */
 class SimpleChannel : public Channel
 {
 public:
--- a/src/node/simple-net-device.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/simple-net-device.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,11 @@
 class SimpleChannel;
 class Node;
 
+/**
+ * \ingroup netdevice
+ * 
+ * \brief simple net device for simple things and testing
+ */
 class SimpleNetDevice : public NetDevice
 {
 public:
--- a/src/node/socket-defaults.cc	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +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
- *
- */
-#include "socket-defaults.h"
-#include "ns3/uinteger.h"
-
-namespace ns3 {
-
-NS_OBJECT_ENSURE_REGISTERED (SocketDefaults);
-
-TypeId SocketDefaults::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::SocketDefaults")
-    .SetParent<Object> ()
-    .AddAttribute ("DefaultSndBufLimit",
-                   "Default maximum receive buffer size (bytes)",
-                   UintegerValue (0xffffffffl),
-                   MakeUintegerAccessor (&SocketDefaults::m_defaultSndBufLimit),
-                   MakeUintegerChecker<uint32_t> ())
-    .AddAttribute ("DefaultRcvBufLimit",
-                   "Default maximum receive buffer size (bytes)",
-                   UintegerValue (0xffffffffl),
-                   MakeUintegerAccessor (&SocketDefaults::m_defaultRcvBufLimit),
-                   MakeUintegerChecker<uint32_t> ())
-    ;
-  return tid;
-}
-
-} // namespace ns3
--- a/src/node/socket-defaults.h	Fri May 30 15:31:50 2008 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +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
- */
-#ifndef SOCKET_DEFAULTS_H
-#define SOCKET_DEFAULTS_H
-
-#include "ns3/object.h"
-
-namespace ns3 {
-
-/**
- * \brief Object to hold socket option defaults
- *
- * This class can be aggregated to a Node and can be used to store
- * socket defaults for a Node.  
- * 
- */
-class SocketDefaults : public Object
-{
-public:
-  static TypeId GetTypeId (void);
-
-private:
-  uint32_t m_defaultSndBufLimit;
-  uint32_t m_defaultRcvBufLimit;
-};
-
-} // namespace ns3
-
-#endif /* SOCKET_DEFAULTS_H */
--- a/src/node/socket-factory.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/socket-factory.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,8 @@
 class Socket;
 
 /**
+ * \ingroup socket
+ *
  * \brief Object to create transport layer instances that provide a 
  * socket API to applications.
  *
--- a/src/node/socket.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/socket.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -30,19 +30,6 @@
 
 namespace ns3 {
 
-#if 0
-TypeId
-Socket::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("ns3::Socket")
-    .SetParent<Object> ()
-    .AddConstructor<Socket> ()
-  ;
-  return tid;
-}
-
-#endif
-
 Socket::Socket (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -123,11 +110,6 @@
   m_receivedData = receivedData;
 }
 
-int Socket::Listen (uint32_t queueLimit)
-{
-  return 0; //XXX the base class version does nothing
-}
-
 void
 Socket::NotifyCloseUnblocks (void)
 {
@@ -138,6 +120,11 @@
   }
 }
 
+int Socket::Listen (uint32_t queueLimit)
+{
+  return 0; //XXX the base class version does nothing
+}
+
 int Socket::Send (const uint8_t* buf, uint32_t size)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -159,6 +146,14 @@
   return Recv (std::numeric_limits<uint32_t>::max(), 0);
 }
 
+int 
+Socket::Recv (uint8_t* buf, uint32_t size, uint32_t flags)
+{
+  Ptr<Packet> p = Recv (size, flags); // read up to "size" bytes
+  memcpy (buf, p->PeekData (), p->GetSize());
+  return p->GetSize ();
+}
+
 int Socket::SendTo (const uint8_t* buf, uint32_t size, const Address &address)
 {
   NS_LOG_FUNCTION_NOARGS ();
@@ -282,42 +277,14 @@
     }
 }
 
+/***************************************************************
+ *           Socket Tags
+ ***************************************************************/
+
 SocketRxAddressTag::SocketRxAddressTag ()  
 {
 }
 
-uint32_t 
-SocketRxAddressTag::GetUid (void)
-{
-  static uint32_t uid = ns3::Tag::AllocateUid<SocketRxAddressTag> ("SocketRxAddressTag.ns3");
-  return uid;
-}
-
-void
-SocketRxAddressTag::Print (std::ostream &os) const
-{
-  os << "address="<< m_address;
-}
-
-uint32_t 
-SocketRxAddressTag::GetSerializedSize (void) const
-{
-  return 0;
-}
-
-void 
-SocketRxAddressTag::Serialize (Buffer::Iterator i) const
-{
-  // for local use in stack only
-}
-
-uint32_t 
-SocketRxAddressTag::Deserialize (Buffer::Iterator i)
-{
-  // for local use in stack only
-  return 0;
-}
-
 void 
 SocketRxAddressTag::SetAddress (Address addr)
 {
@@ -330,40 +297,44 @@
   return m_address;
 }
 
-SocketIpTtlTag::SocketIpTtlTag ()  
+
+TypeId
+SocketRxAddressTag::GetTypeId (void)
 {
+  static TypeId tid = TypeId ("ns3::SocketRxAddressTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SocketRxAddressTag> ()
+    ;
+  return tid;
 }
-
-uint32_t 
-SocketIpTtlTag::GetUid (void)
+TypeId
+SocketRxAddressTag::GetInstanceTypeId (void) const
 {
-  static uint32_t uid = ns3::Tag::AllocateUid<SocketIpTtlTag> ("SocketIpTtlTag.ns3");
-  return uid;
+  return GetTypeId ();
+}
+uint32_t
+SocketRxAddressTag::GetSerializedSize (void) const
+{
+  return m_address.GetSerializedSize ();
 }
-
+void
+SocketRxAddressTag::Serialize (TagBuffer i) const
+{
+  m_address.Serialize (i);
+}
 void
-SocketIpTtlTag::Print (std::ostream &os) const
+SocketRxAddressTag::Deserialize (TagBuffer i)
 {
-  os << "ttl="<< m_ttl;
+  m_address.Deserialize (i);
+}
+void
+SocketRxAddressTag::Print (std::ostream &os) const
+{
+  os << "address=" << m_address;
 }
 
-uint32_t 
-SocketIpTtlTag::GetSerializedSize (void) const
-{
-  return 0;
-}
-
-void 
-SocketIpTtlTag::Serialize (Buffer::Iterator i) const
+SocketIpTtlTag::SocketIpTtlTag ()  
 {
-  // for local use in stack only
-}
-
-uint32_t 
-SocketIpTtlTag::Deserialize (Buffer::Iterator i)
-{
-  // for local use in stack only
-  return 0;
 }
 
 void 
@@ -378,4 +349,41 @@
   return m_ttl;
 }
 
+
+TypeId
+SocketIpTtlTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::SocketIpTtlTag")
+    .SetParent<Tag> ()
+    .AddConstructor<SocketIpTtlTag> ()
+    ;
+  return tid;
+}
+TypeId
+SocketIpTtlTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+
+uint32_t 
+SocketIpTtlTag::GetSerializedSize (void) const
+{ 
+  return 1;
+}
+void 
+SocketIpTtlTag::Serialize (TagBuffer i) const
+{ 
+  i.WriteU8 (m_ttl);
+}
+void 
+SocketIpTtlTag::Deserialize (TagBuffer i)
+{ 
+  m_ttl = i.ReadU8 ();
+}
+void
+SocketIpTtlTag::Print (std::ostream &os) const
+{
+  os << "Ttl=" << (uint32_t) m_ttl;
+}
+
 }//namespace ns3
--- a/src/node/socket.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/socket.h	Wed Jun 04 17:19:32 2008 -0400
@@ -37,19 +37,32 @@
 class Packet;
 
 /**
- * \brief Define a Socket API based on the BSD Socket API.
+ * \ingroup node
+ * \defgroup socket Socket
+ */
+
+/**
+ * \brief A low-level Socket API based loosely on the BSD Socket API.
+ * \ingroup socket
  *
- * In contrast to the original BSD socket API, this API is asynchronous:
- * it does not contain blocking calls. It also uses class ns3::Packet
- * as a fancy byte buffer, allowing data to be passed across the API
- * using an ns3::Packet instead of a raw data pointer.  Other than that, 
- * it tries to stick to the BSD API to make it easier for those who know 
- * the BSD API to use this API.
+ * A few things to keep in mind about this type of socket:
+ * - it uses ns-3 API constructs such as class ns3::Address instead of
+ *   C-style structs
+ * - in contrast to the original BSD socket API, this API is asynchronous:
+ *   it does not contain blocking calls.  Sending and receiving operations
+ *   must make use of the callbacks provided. 
+ * - It also uses class ns3::Packet as a fancy byte buffer, allowing 
+ *   data to be passed across the API using an ns-3 Packet instead of 
+ *   a raw data pointer.  
+ * - Not all of the full POSIX sockets API is supported
+ *
+ * Other than that, it tries to stick to the BSD API to make it 
+ * easier for those who know the BSD API to use this API.  
+ * More details are provided in the ns-3 tutorial.
  */
 class Socket : public Object
 {
 public:
-// static TypeId GetTypeId (void);
 
   Socket (void);
   virtual ~Socket (void);
@@ -224,9 +237,9 @@
   /**
    * \brief Listen for incoming connections.
    * \param queueLimit maximum number of incoming request to queue
-   * \returns XXX an error code
+   * \returns 0 on success, -1 on error (in which case errno is set).
    */
-  virtual int Listen (uint32_t queueLimit);
+  virtual int Listen (uint32_t queueLimit) = 0;
 
   /**
    * \brief Send data (or dummy data) to the remote host
@@ -331,6 +344,19 @@
    */
    Ptr<Packet> Recv (void);
   /**
+   * \brief Recv data (or dummy data) from the remote host
+   * \param buf A pointer to a raw byte buffer to write the data to. 
+   * If the underlying packet was carring null (fake) data, this buffer
+   * will be zeroed up to the length specified by the return value.
+   * \param size Number of bytes (at most) to copy to buf
+   * \param flags any flags to pass to the socket
+   * \returns number of bytes copied into buf
+   * 
+   * This is provided so as to have an API which is closer in appearance 
+   * to that of real network or BSD sockets.  
+   */
+  int Recv (uint8_t* buf, uint32_t size, uint32_t flags);
+  /**
    * Return number of bytes which can be returned from one or 
    * multiple calls to Recv.
    * Must be possible to call this method from the Recv callback.
@@ -372,14 +398,16 @@
 {
 public:
   SocketRxAddressTag ();
-  static uint32_t GetUid (void);
-  void Print (std::ostream &os) const;
-  uint32_t GetSerializedSize (void) const;
-  void Serialize (Buffer::Iterator i) const;
-  uint32_t Deserialize (Buffer::Iterator i);
-
   void SetAddress (Address addr);
   Address GetAddress (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
 private:
   Address m_address;
 };
@@ -392,14 +420,16 @@
 {
 public:
   SocketIpTtlTag ();
-  static uint32_t GetUid (void);
-  void Print (std::ostream &os) const;
-  uint32_t GetSerializedSize (void) const;
-  void Serialize (Buffer::Iterator i) const;
-  uint32_t Deserialize (Buffer::Iterator i);
-
   void SetTtl (uint8_t ttl);
   uint8_t GetTtl (void) const;
+
+  static TypeId GetTypeId (void);  
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer i) const;
+  virtual void Deserialize (TagBuffer i);
+  virtual void Print (std::ostream &os) const;
+
 private:
   uint8_t m_ttl;
 };
--- a/src/node/tcp-socket-factory.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/tcp-socket-factory.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 class Socket;
 
 /**
+ * \ingroup socket
+ *
  * \brief API to create TCP socket instances 
  *
  * This abstract class defines the API for TCP sockets.
--- a/src/node/tcp-socket.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/tcp-socket.h	Wed Jun 04 17:19:32 2008 -0400
@@ -36,6 +36,8 @@
 class Packet;
 
 /**
+ * \ingroup socket
+ *
  * \brief (abstract) base class of all TcpSockets
  *
  * This class exists solely for hosting TcpSocket attributes that can
--- a/src/node/udp-socket-factory.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/udp-socket-factory.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,6 +27,8 @@
 class Socket;
 
 /**
+ * \ingroup socket
+ *
  * \brief API to create UDP socket instances 
  *
  * This abstract class defines the API for UDP socket factory.
--- a/src/node/udp-socket.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/udp-socket.h	Wed Jun 04 17:19:32 2008 -0400
@@ -35,6 +35,8 @@
 class Packet;
 
 /**
+ * \ingroup socket
+ *
  * \brief (abstract) base class of all UdpSockets
  *
  * This class exists solely for hosting UdpSocket attributes that can
--- a/src/node/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/node/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -11,6 +11,7 @@
         'node.cc',
         'ipv4-address.cc',
         'ipv4-address-generator.cc',
+        'ipv4-header.cc',
         'net-device.cc',
 	'address-utils.cc',
         'llc-snap-header.cc',
@@ -46,6 +47,7 @@
         'node.h',
         'ipv4-address.h',
         'ipv4-address-generator.h',
+        'ipv4-header.h',
         'net-device.h',
 	'address-utils.h',
         'ipv4-route.h',
--- a/src/routing/global-routing/global-route-manager-impl.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -1275,7 +1275,7 @@
 // the local side of the point-to-point links found on the node described by
 // the vertex <v>.
 //
-          for (uint32_t j = 0; j < nLinkRecords; j += 2)
+          for (uint32_t j = 0; j < nLinkRecords; ++j)
             {
 //
 // We are only concerned about point-to-point links
--- a/src/routing/global-routing/global-router-interface.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/routing/global-routing/global-router-interface.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -584,7 +584,7 @@
               plr->SetLinkId (addrLocal.CombineMask(maskLocal));
               // Link Data is network mask; convert to Ipv4Address
               Ipv4Address maskLocalAddr;
-              maskLocalAddr.Set(maskLocal.GetHostOrder ());
+              maskLocalAddr.Set(maskLocal.Get ());
               plr->SetLinkData (maskLocalAddr);
               plr->SetMetric (metricLocal);
               pLSA->AddLinkRecord(plr);
@@ -689,7 +689,7 @@
           plr = new GlobalRoutingLinkRecord;
           plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
           plr->SetLinkId (addrRemote);
-          plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder()));  // Frown
+          plr->SetLinkData (Ipv4Address(maskRemote.Get()));  // Frown
           plr->SetMetric (metricLocal);
           pLSA->AddLinkRecord (plr);
           plr = 0;
--- a/src/routing/olsr/olsr-agent-impl.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/routing/olsr/olsr-agent-impl.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -312,7 +312,8 @@
   receivedPacket = socket->Recv ();
 
   SocketRxAddressTag tag;
-  bool found = receivedPacket->PeekTag (tag);
+  bool found;
+  found = receivedPacket->FindFirstMatchingTag (tag);
   NS_ASSERT (found);
   Address sourceAddress = tag.GetAddress ();
 
--- a/src/routing/olsr/olsr-header.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/routing/olsr/olsr-header.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -211,7 +211,7 @@
   i.WriteU8 (m_messageType);
   i.WriteU8 (m_vTime);
   i.WriteHtonU16 (GetSerializedSize ());
-  i.WriteHtonU32 (m_originatorAddress.GetHostOrder ());
+  i.WriteHtonU32 (m_originatorAddress.Get ());
   i.WriteU8 (m_timeToLive);
   i.WriteU8 (m_hopCount);
   i.WriteHtonU16 (m_messageSequenceNumber);
@@ -293,7 +293,7 @@
   for (std::vector<Ipv4Address>::const_iterator iter = this->interfaceAddresses.begin ();
        iter != this->interfaceAddresses.end (); iter++)
     {
-      i.WriteHtonU32 (iter->GetHostOrder ());
+      i.WriteHtonU32 (iter->Get ());
     }
 }
 
@@ -364,7 +364,7 @@
       for (std::vector<Ipv4Address>::const_iterator neigh_iter = lm.neighborInterfaceAddresses.begin ();
            neigh_iter != lm.neighborInterfaceAddresses.end (); neigh_iter++)
         {
-          i.WriteHtonU32 (neigh_iter->GetHostOrder ());
+          i.WriteHtonU32 (neigh_iter->Get ());
         }
     }
 }
@@ -432,7 +432,7 @@
   for (std::vector<Ipv4Address>::const_iterator iter = this->neighborAddresses.begin ();
        iter != this->neighborAddresses.end (); iter++)
     {
-      i.WriteHtonU32 (iter->GetHostOrder ());
+      i.WriteHtonU32 (iter->Get ());
     }
 }
 
@@ -478,8 +478,8 @@
 
   for (size_t n = 0; n < this->associations.size (); ++n)
     {
-      i.WriteHtonU32 (this->associations[n].address.GetHostOrder ());
-      i.WriteHtonU32 (this->associations[n].mask.GetHostOrder ());
+      i.WriteHtonU32 (this->associations[n].address.Get ());
+      i.WriteHtonU32 (this->associations[n].mask.Get ());
     }
 }
 
--- a/src/simulator/event-id.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/event-id.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,11 +29,24 @@
 class EventImpl;
 
 /**
+ * \ingroup simulator
  * \brief an identifier for simulation events.
+ *
+ * Each EventId identifies a unique event scheduled with one
+ * of the many Simulator::Schedule methods. This EventId can
+ * be used to Cancel or Remove events after they are scheduled
+ * with Simulator::Cancel or Simulator::Remove.
+ *
+ * The important thing to remember about this class is that
+ * every variable of this type is _always_ in a valid state, 
+ * even when it has not been assigned an EventId coming from a Schedule
+ * method: calling Cancel, IsRunning, IsExpired or passing around
+ * instances of this object will not result in crashes or memory leaks.
  */
 class EventId {
 public:
   EventId ();
+  // internal.
   EventId (const Ptr<EventImpl> &impl, uint64_t ts, uint32_t uid);
   /**
    * This method is syntactic sugar for the ns3::Simulator::cancel
@@ -46,6 +59,11 @@
    * \returns true if the event has expired, false otherwise.
    */
   bool IsExpired (void) const;
+  /**
+   * This method is syntactic sugar for the ns3::Simulator::isExpired
+   * method.
+   * \returns true if the event has not expired, false otherwise.
+   */
   bool IsRunning (void) const;
 public:
   /* The following methods are semi-private
--- a/src/simulator/event-impl.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/event-impl.h	Wed Jun 04 17:19:32 2008 -0400
@@ -24,6 +24,17 @@
 
 namespace ns3 {
 
+/**
+ * \ingroup simulator
+ * \brief a simulation event
+ *
+ * Each subclass of this base class represents a simulation event. The
+ * EventImpl::Invoke method will be invoked by the simulation engine
+ * when the time associated to this event expires. This class is
+ * obviously (there are Ref and Unref methods) reference-counted and
+ * most subclasses are usually created by one of the many Simulator::Schedule
+ * methods.
+ */
 class EventImpl
 {
 public:
@@ -31,8 +42,21 @@
   inline void Ref (void) const;
   inline void Unref (void) const;
   virtual ~EventImpl () = 0;
+  /**
+   * Called by the simulation engine to notify the event that it has expired.
+   */
   void Invoke (void);
+  /**
+   * Marks the event as 'canceled'. The event will not be removed from
+   * the event list but the simulation engine will check its canceled status
+   * before calling Invoke.
+   */
   void Cancel (void);
+  /**
+   * \returns true if the event has been canceled.
+   *
+   * Invoked by the simulation engine before calling Invoke.
+   */
   bool IsCancelled (void);
 protected:
   virtual void Notify (void) = 0;
--- a/src/simulator/heap-scheduler.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/heap-scheduler.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -18,17 +18,6 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  *
- * This code started as a c++ translation of a java-based code written in 2005
- * to implement a heap sort. Which explains the "Copyright Mathieu Lacage" at the
- * top of this file.
- *
- * What is smart about this code ?
- *  - it does not use the index 0 in the array to avoid having to convert
- *    C-style array indexes (which start at zero) and heap-style indexes
- *    (which start at 1). This is why _all_ indexes start at 1, and that
- *    the index of the root is 1.
- *  - It uses a slightly non-standard while loop for top-down heapify
- *    to move one if statement out of the loop.
  */
 
 #include "heap-scheduler.h"
--- a/src/simulator/heap-scheduler.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/heap-scheduler.h	Wed Jun 04 17:19:32 2008 -0400
@@ -29,6 +29,23 @@
 
 class EventHolder;
 
+/**
+ * \ingroup scheduler
+ * \brief a binary heap event scheduler
+ * 
+ * This code started as a c++ translation of a java-based code written in 2005
+ * to implement a heap sort. So, this binary heap is really a pretty 
+ * straightforward implementation of the classic data structure. Not much to say
+ * about it.
+ *
+ * What is smart about this code ?
+ *  - it does not use the index 0 in the array to avoid having to convert
+ *    C-style array indexes (which start at zero) and heap-style indexes
+ *    (which start at 1). This is why _all_ indexes start at 1, and that
+ *    the index of the root is 1.
+ *  - It uses a slightly non-standard while loop for top-down heapify
+ *    to move one if statement out of the loop.
+ */
 class HeapScheduler : public Scheduler {
 public:
   HeapScheduler ();
--- a/src/simulator/list-scheduler.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/list-scheduler.h	Wed Jun 04 17:19:32 2008 -0400
@@ -31,6 +31,13 @@
 
 class EventImpl;
 
+/**
+ * \ingroup scheduler
+ * \brief a std::list event scheduler
+ *
+ * This class implements the an event scheduler using an std::list
+ * data structure, that is, a double linked-list.
+ */
 class ListScheduler : public Scheduler {
  public:
   ListScheduler ();
--- a/src/simulator/map-scheduler.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/map-scheduler.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,13 @@
 
 class EventImpl;
 
+/**
+ * \ingroup scheduler
+ * \brief a std::map event scheduler
+ *
+ * This class implements the an event scheduler using an std::map 
+ * data structure.
+ */
 class MapScheduler : public Scheduler {
 public:
   MapScheduler ();
--- a/src/simulator/nstime.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/nstime.h	Wed Jun 04 17:19:32 2008 -0400
@@ -60,6 +60,11 @@
 
 
 /**
+ * \ingroup simulator
+ * \defgroup time Time
+ */
+/**
+ * \ingroup time
  * \brief keep track of time unit.
  *
  * This template class is used to keep track of the value 
--- a/src/simulator/scheduler.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/scheduler.h	Wed Jun 04 17:19:32 2008 -0400
@@ -28,6 +28,11 @@
 namespace ns3 {
 
 /**
+ * \ingroup simulator
+ * \defgroup scheduler Scheduler
+ */
+/**
+ * \ingroup scheduler
  * \brief Maintain the event list
  *
  * This base class specifies the interface used to maintain the 
@@ -40,13 +45,6 @@
  *   - ns3::Scheduler::RemoveNext
  *   - ns3::Scheduler::Remove
  *
- * If you need to provide a new event list scheduler without
- * editing the main simulator class, you need to also implement
- * a subclass of the ns3::SchedulerFactory base class and
- * feed it to ns3::Simulator::setExternal.
- * The simplest example of a scheduler is the linked-list
- * scheduler included in ns3: see the files 
- * src/simulator/scheduler-list.h and src/simulator/scheduler-list.cc
  */
 class Scheduler : public Object
 {
--- a/src/simulator/simulator.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/simulator.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -68,7 +68,7 @@
   bool IsFinished (void) const;
   Time Next (void) const;
   void Stop (void);
-  void StopAt (Time const &time);
+  void Stop (Time const &time);
   EventId Schedule (Time const &time, const Ptr<EventImpl> &event);
   EventId ScheduleNow (const Ptr<EventImpl> &event);
   EventId ScheduleDestroy (const Ptr<EventImpl> &event);
@@ -115,8 +115,8 @@
     .AddAttribute ("Scheduler",
                    "The Scheduler used to handle all simulation events.",
                    PointerValue (),
-                   // XXX: allow getting the scheduler too.
-                   MakePointerAccessor (&SimulatorPrivate::SetScheduler),
+                   MakePointerAccessor (&SimulatorPrivate::SetScheduler,
+                                        &SimulatorPrivate::GetScheduler),
                    MakePointerChecker<Scheduler> ())
     ;
   return tid;
@@ -249,10 +249,11 @@
   m_stop = true;
 }
 void 
-SimulatorPrivate::StopAt (Time const &at)
+SimulatorPrivate::Stop (Time const &time)
 {
-  NS_ASSERT (at.IsPositive ());
-  m_stopAt = at.GetTimeStep ();
+  NS_ASSERT (time.IsPositive ());
+  Time absolute = Simulator::Now () + time;
+  m_stopAt = absolute.GetTimeStep ();
 }
 EventId
 SimulatorPrivate::Schedule (Time const &time, const Ptr<EventImpl> &event)
@@ -485,9 +486,9 @@
   GetPriv ()->Stop ();
 }
 void 
-Simulator::StopAt (Time const &at)
+Simulator::Stop (Time const &time)
 {
-  GetPriv ()->StopAt (at);
+  GetPriv ()->Stop (time);
 }
 Time
 Simulator::Now (void)
@@ -1125,7 +1126,7 @@
   Simulator::Destroy ();
 
   Simulator::Schedule (Seconds (10.0), &SimulatorTests::baz1, this, 0);
-  Simulator::StopAt (Seconds (1.0));
+  Simulator::Stop (Seconds (1.0));
   Simulator::Run ();
   Simulator::Destroy ();
 
--- a/src/simulator/simulator.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/simulator.h	Wed Jun 04 17:19:32 2008 -0400
@@ -35,6 +35,8 @@
 class SchedulerFactory;
 
 /**
+ * \ingroup simulator
+ *
  * \brief Control the scheduling of simulation events. 
  *
  * The internal simulation clock is maintained
@@ -59,7 +61,11 @@
    */
   static void EnableParallelSimulation (void);
   /**
-   * XXX
+   * \param scheduler a new event scheduler
+   *
+   * The event scheduler can be set at any time: the events scheduled
+   * in the previous scheduler will be transfered to the new scheduler
+   * before we start to use it.
    */
   static void SetScheduler (Ptr<Scheduler> scheduler);
 
@@ -126,12 +132,13 @@
    */
   static void Stop (void);
   /**
-   * Force the Simulator::run method to return to the caller
-   * when the expiration time of the next event to be processed 
-   * is greater than or equal to the stop time.
-   * @param time the stop time.
+   * Force the Simulator::run method to return to the caller when the
+   * expiration time of the next event to be processed is greater than
+   * or equal to the stop time.  The stop time is relative to the
+   * current simulation time.
+   * @param time the stop time, relative to the current time.
    */
-  static void StopAt (Time const &time);
+  static void Stop (Time const &time);
 
   /**
    * Schedule an event to expire when the time "now + time" 
--- a/src/simulator/time.cc	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/time.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -271,7 +271,6 @@
   else
     {
       is.setstate (std::ios_base::failbit);
-      // XXX: problem ?
     }
   return is;
 }
--- a/src/simulator/timer.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/timer.h	Wed Jun 04 17:19:32 2008 -0400
@@ -30,6 +30,8 @@
 class TimerImpl;
 
 /**
+ * \ingroup simulator
+ *
  * \brief a simple Timer class
  *
  * A timer is used to hold together a delay, a function to invoke
--- a/src/simulator/watchdog.h	Fri May 30 15:31:50 2008 -0400
+++ b/src/simulator/watchdog.h	Wed Jun 04 17:19:32 2008 -0400
@@ -27,12 +27,26 @@
 
 class TimerImpl;
 
+/**
+ * \ingroup simulator
+ * \brief a very simple watchdog
+ *
+ * If you don't ping the watchdog sufficiently often, it triggers its
+ * listening function.
+ */
 class Watchdog 
 {
 public:
   Watchdog ();
   ~Watchdog ();
 
+  /**
+   * \param delay the watchdog delay
+   *
+   * After a call to this method, the watchdog will not be triggered
+   * until the delay specified has been expired. This operation is
+   * sometimes named "re-arming" a watchdog in some operating systems.
+   */
   void Ping (Time delay);
 
   /**
--- a/src/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/src/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -47,6 +47,7 @@
 def configure(conf):
     conf.sub_config('core')
     conf.sub_config('simulator')
+    conf.sub_config('contrib')
 
     blddir = os.path.abspath(os.path.join(conf.m_blddir, conf.env.variant()))
     conf.env['NS3_MODULE_PATH'] = [blddir]
--- a/utils/bench-packets.cc	Fri May 30 15:31:50 2008 -0400
+++ b/utils/bench-packets.cc	Wed Jun 04 17:19:32 2008 -0400
@@ -22,6 +22,7 @@
 #include "ns3/packet-metadata.h"
 #include <iostream>
 #include <sstream>
+#include <string>
 
 using namespace ns3;
 
@@ -39,6 +40,7 @@
   virtual void Serialize (Buffer::Iterator start) const;
   virtual uint32_t Deserialize (Buffer::Iterator start);
 private:
+  static std::string GetTypeName (void);
   bool m_ok;
 };
 
@@ -55,12 +57,19 @@
 }
 
 template <int N>
+std::string 
+BenchHeader<N>::GetTypeName (void)
+{
+  std::ostringstream oss;
+  oss << "ns3::BenchHeader<" << N << ">";
+  return oss.str ();
+}
+
+template <int N>
 TypeId 
 BenchHeader<N>::GetTypeId (void)
 {
-  std::ostringstream oss;
-  oss << "ns3::BenchHeader<"<<N<<">";
-  static TypeId tid = TypeId (oss.str ().c_str ())
+  static TypeId tid = TypeId (GetTypeName ().c_str ())
     .SetParent<Header> ()
     ;
   return tid;
@@ -105,10 +114,75 @@
   return N;
 }
 
+template <int N>
+class BenchTag : public Tag
+{
+public:
+  static std::string GetName (void) {
+    std::ostringstream oss;
+    oss << "anon::BenchTag<" << N << ">";
+    return oss.str ();
+  }
+  static TypeId GetTypeId (void) {
+    static TypeId tid = TypeId (GetName ().c_str ())
+      .SetParent<Tag> ()
+      .AddConstructor<BenchTag > ()
+      .HideFromDocumentation ()
+      ;
+    return tid;
+  }
+  virtual TypeId GetInstanceTypeId (void) const {
+    return GetTypeId ();
+  }
+  virtual uint32_t GetSerializedSize (void) const {
+    return N;
+  }
+  virtual void Serialize (TagBuffer buf) const {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        buf.WriteU8 (N);
+      }
+  }
+  virtual void Deserialize (TagBuffer buf) {
+    for (uint32_t i = 0; i < N; ++i)
+      {
+        buf.ReadU8 ();
+      }
+  }
+  virtual void Print (std::ostream &os) const {
+    os << "N=" << N;
+  }
+  BenchTag ()
+    : Tag () {}
+};
 
 
 static void 
-benchPtrA (uint32_t n)
+benchD (uint32_t n)
+{
+  BenchHeader<25> ipv4;
+  BenchHeader<8> udp;
+  BenchTag<16> tag1;
+  BenchTag<17> tag2;
+
+  for (uint32_t i = 0; i < n; i++) {
+    Ptr<Packet> p = Create<Packet> (2000);
+    p->AddTag (tag1);
+    p->AddHeader (udp);
+    p->FindFirstMatchingTag (tag1);
+    p->AddTag (tag2);
+    p->AddHeader (ipv4);
+    Ptr<Packet> o = p->Copy ();
+    o->RemoveHeader (ipv4);
+    p->FindFirstMatchingTag (tag2);
+    o->RemoveHeader (udp);
+  }
+}
+
+
+
+static void 
+benchA (uint32_t n)
 {
   BenchHeader<25> ipv4;
   BenchHeader<8> udp;
@@ -124,7 +198,7 @@
 }
 
 static void 
-benchPtrB (uint32_t n)
+benchB (uint32_t n)
 {
   BenchHeader<25> ipv4;
   BenchHeader<8> udp;
@@ -137,7 +211,7 @@
 }
 
 static void
-ptrC2 (Ptr<Packet> p)
+C2 (Ptr<Packet> p)
 {
   BenchHeader<8> udp;
 
@@ -145,15 +219,15 @@
 }
 
 static void 
-ptrC1 (Ptr<Packet> p)
+C1 (Ptr<Packet> p)
 {
   BenchHeader<25> ipv4;
   p->RemoveHeader (ipv4);
-  ptrC2 (p);
+  C2 (p);
 }
 
 static void
-benchPtrC (uint32_t n)
+benchC (uint32_t n)
 {
   BenchHeader<25> ipv4;
   BenchHeader<8> udp;
@@ -162,28 +236,10 @@
     Ptr<Packet> p = Create<Packet> (2000);
     p->AddHeader (udp);
     p->AddHeader (ipv4);
-    ptrC1 (p);
+    C1 (p);
   }
 }
 
-#if 0
-static void
-benchPrint (uint32_t n)
-{
-  PacketPrinter printer;
-  BenchHeader<25> ipv4;
-  BenchHeader<8> udp;
-  Ptr<Packet> p = Create<Packet> (2000);
-  p->AddHeader (udp);
-  p->AddHeader (ipv4);
-
-  for (uint32_t i = 0; i < n; i++) 
-    {
-      p->Print (std::cerr, printer);
-    }  
-}
-#endif
-
 
 static void
 runBench (void (*bench) (uint32_t), uint32_t n, char const *name)
@@ -218,15 +274,17 @@
     }
   std::cout << "Running bench-packets with n=" << n << std::endl;
 
-  Packet::EnableMetadata ();
-  runBench (&benchPtrA, n, "a");
-  runBench (&benchPtrB, n, "b");
-  runBench (&benchPtrC, n, "c");
+  runBench (&benchA, n, "a");
+  runBench (&benchB, n, "b");
+  runBench (&benchC, n, "c");
+  runBench (&benchD, n, "d");
 
-  //runBench (&benchPrint, n, "print");
-  runBench (&benchPtrA, n, "meta-a");
-  runBench (&benchPtrB, n, "meta-b");
-  runBench (&benchPtrC, n, "meta-c");
+  Packet::EnableMetadata ();
+  runBench (&benchA, n, "meta-a");
+  runBench (&benchB, n, "meta-b");
+  runBench (&benchC, n, "meta-c");
+  runBench (&benchD, n, "meta-d");
+
 
 
   return 0;
--- a/wscript	Fri May 30 15:31:50 2008 -0400
+++ b/wscript	Wed Jun 04 17:19:32 2008 -0400
@@ -217,6 +217,9 @@
         conf.env['NS3_ENABLED_MODULES'] = ['ns3-'+mod for mod in
                                            Params.g_options.enable_modules.split(',')]
 
+    ## we cannot run regression tests without diff
+    conf.find_program('diff', var='DIFF')
+
 
 def create_ns3_program(bld, name, dependencies=('simulator',)):
     program = bld.create_obj('cpp', 'program')
@@ -326,11 +329,14 @@
     #ut.want_to_see_test_error = True
     #ut.run()
     #ut.print_results()
+    env = Params.g_build.env_of_name('default')
 
     if Params.g_commands['check']:
         _run_waf_check()
 
     if Params.g_options.regression or Params.g_options.regression_generate:
+        if not env['DIFF']:
+            Params.fatal("Cannot run regression tests: the 'diff' program is not installed.")
         _dir = os.getcwd()
         os.chdir("regression")
         try:
@@ -657,6 +663,8 @@
 class Regression(object):
     def __init__(self, testdir):
         self.testdir = testdir
+        env = Params.g_build.env_of_name('default')
+        self.diff = env['DIFF']
 
     def run_test(self, verbose, generate, refDirName, testName):
         refTestDirName = os.path.join(refDirName, (testName + ".ref"))
@@ -692,7 +700,7 @@
 
             if verbose:
                 #diffCmd = "diff traces " + refTestDirName + " | head"
-                diffCmd = subprocess.Popen(["diff", "traces", refTestDirName],
+                diffCmd = subprocess.Popen([self.diff, "traces", refTestDirName],
                                            stderr=subprocess.PIPE, stdout=subprocess.PIPE)
                 headCmd = subprocess.Popen("head", stdin=diffCmd.stdout)
                 rc2 = headCmd.wait()
@@ -700,7 +708,7 @@
                 rc1 = diffCmd.wait()
                 rc = rc1 or rc2
             else:
-                diffCmd = "diff traces " + refTestDirName + \
+                diffCmd = self.diff +" traces " + refTestDirName + \
                     " > /dev/null 2>&1"
                 rc = os.system(diffCmd)
             if rc:
@@ -710,7 +718,7 @@
                 print "Traces in directory: traces"
                 print "Rerun regression test as: " + \
                     "\"./waf --regression --regression-tests=test-" + testName + "\""
-                print "Then do \"diff -u regression/traces regression/" + refTestDirName + \
+                print "Then do \"diff -u regression/" + refTestDirName + " regression/traces" \
                     "\" for details"
                 print "----------"
             return rc