merge with HEAD
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Wed, 27 Feb 2008 22:19:39 +0100
changeset 2503 e667dc0f350e
parent 2357 d64b1561b1c2 (current diff)
parent 2502 50d0da37f02f (diff)
child 2504 da3ec9cc3ba3
merge with HEAD
examples/simple-point-to-point-olsr.cc
samples/main-ap-wifi.cc
src/applications/onoff/onoff-application.cc
src/applications/onoff/onoff-application.h
src/common/error-model.cc
src/core/object.h
src/devices/wifi/wifi-net-device.cc
src/devices/wifi/wifi-net-device.h
src/devices/wifi/wifi-phy.cc
src/internet-node/ipv4-l3-protocol.cc
src/internet-node/tcp-l4-protocol.cc
src/internet-node/tcp-l4-protocol.h
src/internet-node/udp-l4-protocol.cc
src/internet-node/udp-l4-protocol.h
src/internet-node/udp-socket.cc
src/mobility/ns2-mobility-file-topology.cc
src/mobility/ns2-mobility-file-topology.h
src/mobility/position-allocator.cc
src/mobility/position-allocator.h
src/mobility/random-position.cc
src/mobility/random-position.h
src/mobility/random-waypoint-mobility-model.cc
src/node/ipv4-address.h
src/routing/olsr/olsr-agent-impl.cc
src/routing/olsr/olsr-agent-impl.h
src/simulator/simulator.cc
utils/mobility-visualizer-model.cc
--- a/examples/csma-broadcast.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/csma-broadcast.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -154,30 +154,36 @@
   // Create the OnOff application to send UDP datagrams of size
   // 512 bytes (default) at a rate of 500 Kb/s (default) from n0
   NS_LOG_INFO ("Create Applications.");
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("255.255.255.255", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("255.255.255.255", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.0));
   ooff->Stop (Seconds(10.0));
   
   // Create an optional packet sink to receive these packets
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n1,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n1,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
   sink->Stop (Seconds (10.0));
 
   // Create an optional packet sink to receive these packets
-  sink = CreateObject<PacketSink> (
-    n2,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  sink = CreateObjectWith<PacketSink> (
+                                       "Node", n2,
+                                       "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                       "Protocol", TypeId::LookupByName ("Udp"));
+  n2->AddApplication (sink);
+
   // Start the sink
   sink->Start (Seconds (1.0));
   sink->Stop (Seconds (10.0));
--- a/examples/csma-multicast.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/csma-multicast.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -52,6 +52,7 @@
 #include "ns3/ipv4-route.h"
 #include "ns3/onoff-application.h"
 #include "ns3/packet-sink.h"
+#include "ns3/uinteger.h"
 
 using namespace ns3;
 
@@ -281,14 +282,16 @@
 
   // Configure a multicast packet generator that generates a packet
   // every few seconds
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress (multicastGroup, port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0),
-    DataRate ("255b/s"),
-    128);
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress (multicastGroup, port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0),
+                                        "DataRate", DataRate ("255b/s"),
+                                        "PacketSize", Uinteger (128));
+  n0->AddApplication (ooff);
 //
 // Tell the application when to start and stop.
 //
@@ -298,10 +301,12 @@
   // Create an optional packet sink to receive these packets
   // If you enable logging on this (above) it will print a log statement
   // for every packet received
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n4,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n4,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n4->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
   sink->Stop (Seconds (10.0));
--- a/examples/csma-one-subnet.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/csma-one-subnet.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -165,12 +165,15 @@
 //
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.1.2", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.1.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
+
 //
 // Tell the application when to start and stop.
 //
@@ -179,12 +182,13 @@
 // 
 // Create a similar flow from n3 to n0, starting at time 1.1 seconds
 //
-  ooff = CreateObject<OnOffApplication> (
-    n3, 
-    InetSocketAddress ("10.1.1.1", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n3, 
+                                             "Remote", Address (InetSocketAddress ("10.1.1.1", port)), 
+                                             "Protocol", TypeId::LookupByName ("Udp"),
+                                             "OnTime", ConstantVariable(1), 
+                                             "OffTime", ConstantVariable(0));
+  n3->AddApplication (ooff);
 
   ooff->Start(Seconds(1.1));
   ooff->Stop (Seconds(10.0));
--- a/examples/csma-packet-socket.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/csma-packet-socket.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -38,6 +38,7 @@
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
 #include "ns3/log.h"
+#include "ns3/string.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -61,7 +62,10 @@
 static Ptr<CsmaNetDevice>
 CreateCsmaDevice (Ptr<Node> node, Ptr<CsmaChannel> channel)
 {
-  Ptr<CsmaNetDevice> device = CreateObject<CsmaNetDevice> (node);
+  Ptr<CsmaNetDevice> device = CreateObjectWith<CsmaNetDevice> ("Node", node, 
+                                                               "Address", Mac48Address::Allocate (),
+                                                               "EncapsulationMode", String ("Llc"));
+  node->AddDevice (device);
   device->Attach (channel);
   Ptr<Queue> queue = Queue::CreateDefault ();
   device->AddQueue (queue);
@@ -134,23 +138,26 @@
   // 210 bytes at a rate of 448 Kb/s
   // from n0 to n1
   NS_LOG_INFO ("Create Applications.");
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    n0ToN1,
-    "Packet",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (n0ToN1),
+                                        "Protocol", TypeId::LookupByName ("Packet"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.0));
   ooff->Stop (Seconds(10.0));
 
   // Create a similar flow from n3 to n0, starting at time 1.1 seconds
-  ooff = CreateObject<OnOffApplication> (
-    n3, 
-    n3ToN0,
-    "Packet",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n3, 
+                                             "Remote", Address (n3ToN0),
+                                             "Protocol", TypeId::LookupByName ("Packet"),
+                                             "OnTime", ConstantVariable(1), 
+                                             "OffTime", ConstantVariable(0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.1));
   ooff->Stop (Seconds(10.0));
--- a/examples/mixed-global-routing.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/mixed-global-routing.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -42,6 +42,7 @@
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/config.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -65,6 +66,7 @@
 #include "ns3/point-to-point-topology.h"
 #include "ns3/onoff-application.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/uinteger.h"
 
 using namespace ns3;
 
@@ -110,10 +112,8 @@
   // topology code
   DefaultValue::Bind ("Queue", "DropTailQueue");
 
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
-
-  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
+  Config::SetDefault ("OnOffApplication::PacketSize", Uinteger (210));
+  Config::SetDefault ("OnOffApplication::DataRate", DataRate ("448kb/s"));
 
   // Allow the user to override any of the defaults and the above
   // Bind ()s at run-time, via command-line arguments
@@ -191,14 +191,16 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.3.2", port), 
-    "Udp",
-    ConstantVariable (1), 
-    ConstantVariable (0),
-    DataRate("300bps"),
-    50);
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.3.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable (1), 
+                                        "OffTime", ConstantVariable (0),
+                                        "DataRate", DataRate("300bps"),
+                                        "PacketSize", Uinteger (50));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds (1.0));
   ooff->Stop (Seconds (10.0));
--- a/examples/simple-alternate-routing.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/simple-alternate-routing.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -43,6 +43,8 @@
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/config.h"
+#include "ns3/uinteger.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -105,8 +107,8 @@
   // instantiate, when the queue factory is invoked in the topology code
   DefaultValue::Bind ("Queue", "DropTailQueue");
 
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "300b/s");
+  Config::SetDefault ("OnOffApplication::PacketSize", Uinteger (210));
+  Config::SetDefault ("OnOffApplication::DataRate", DataRate ("300b/s"));
 
   // The below metric, if set to 3 or higher, will cause packets between
   // n1 and n3 to take the 2-hop route through n2
@@ -182,21 +184,25 @@
   uint16_t port = 9;   // Discard port (RFC 863)
 
   // Create a flow from n3 to n1, starting at time 1.1 seconds
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n3, 
-    InetSocketAddress ("10.1.1.1", port),
-    "Udp",
-    ConstantVariable (1), 
-    ConstantVariable (0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n3, 
+                                        "Remote", Address (InetSocketAddress ("10.1.1.1", port)),
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable (1), 
+                                        "OffTime", ConstantVariable (0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds (1.1));
   ooff->Stop (Seconds (10.0));
 
   // Create a packet sink to receive these packets
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n1, 
-    InetSocketAddress (Ipv4Address::GetAny (), port), 
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n1, 
+                                  "Remote", Address (InetSocketAddress (Ipv4Address::GetAny (), port)), 
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.1));
   sink->Stop (Seconds (10.0));
--- a/examples/simple-error-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/simple-error-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -43,6 +43,9 @@
 #include "ns3/command-line.h"
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
+#include "ns3/config.h"
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -64,6 +67,7 @@
 #include "ns3/onoff-application.h"
 #include "ns3/packet-sink.h"
 #include "ns3/error-model.h"
+#include "ns3/double.h"
 
 using namespace ns3;
 
@@ -78,15 +82,12 @@
   LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_INFO);
 #endif
 
-  // Set up some default values for the simulation.  Use the Bind()
-  // technique to tell the system what subclass of ErrorModel to use
-  DefaultValue::Bind ("ErrorModel", "RateErrorModel");
   // Set a few parameters
-  DefaultValue::Bind ("RateErrorModelErrorRate", "0.01");
-  DefaultValue::Bind ("RateErrorModelErrorUnit", "EU_PKT");
-
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+  Config::SetDefault ("RateErrorModel::ErrorRate", Double (0.01));
+  Config::SetDefault ("RateErrorModel::ErrorUnit", String ("EU_PKT"));
+  
+  Config::SetDefault ("OnOffApplication::PacketSize", Uinteger (210));
+  Config::SetDefault ("OnOffApplication::DataRate", DataRate ("448kb/s"));
 
 
   // Allow the user to override any of the defaults and the above
@@ -142,41 +143,46 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.3.2", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.3.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.0));
   ooff->Stop (Seconds(10.0));
 
   // Create an optional packet sink to receive these packets
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n3,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  Ptr<PacketSink> sink = CreateObjectWith<PacketSink> (
+                                                       "Node", n3,
+                                                       "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                                       "Protocol", TypeId::LookupByName ("Udp"));
+  n3->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
   sink->Stop (Seconds (10.0));
 
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
-  ooff = CreateObject<OnOffApplication> (
-    n3, 
-    InetSocketAddress ("10.1.2.1", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                         "Node", n3, 
+                                         "Remote", Address (InetSocketAddress ("10.1.2.1", port)), 
+                                         "Protocol", TypeId::LookupByName ("Udp"),
+                                         "OnTime", ConstantVariable(1), 
+                                         "OffTime", ConstantVariable(0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.1));
   ooff->Stop (Seconds(10.0));
 
   // Create a packet sink to receive these packets
-  sink = CreateObject<PacketSink> (
-    n1,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  sink = CreateObjectWith<PacketSink> (
+                                   "Node", n1,
+                                   "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                   "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.1));
   sink->Stop (Seconds (10.0));
@@ -200,16 +206,8 @@
     (n3, channel2);
   // Create an ErrorModel based on the implementation (constructor)
   // specified by the default classId
-  Ptr<ErrorModel> em = ErrorModel::CreateDefault ();
-  NS_ASSERT (em != 0);
-  // Now, query interface on the resulting em pointer to see if a 
-  // RateErrorModel interface exists.  If so, set the packet error rate
-  Ptr<RateErrorModel> bem = em->GetObject<RateErrorModel> ();
-  if (bem)
-    { 
-      bem->SetRandomVariable (UniformVariable ());
-      bem->SetRate (0.001);
-    }
+  Ptr<RateErrorModel> em = CreateObjectWith<RateErrorModel> ("RanVar", UniformVariable (0.0, 1.0),
+                                                             "Rate", Double (0.001));
   nd3->AddReceiveErrorModel (em);
 
   // Now, let's use the ListErrorModel and explicitly force a loss
--- a/examples/simple-global-routing.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/simple-global-routing.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -48,6 +48,8 @@
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/config.h"
+#include "ns3/uinteger.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -110,8 +112,8 @@
   // instantiate, when the queue factory is invoked in the topology code
   DefaultValue::Bind ("Queue", "DropTailQueue");
 
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+  Config::SetDefault ("OnOffApplication::PacketSize", Uinteger (210));
+  Config::SetDefault ("OnOffApplication::DataRate", DataRate ("448kb/s"));
 
   //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
 
@@ -163,42 +165,45 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.3.2", port), 
-    "Udp",
-    ConstantVariable (1), 
-    ConstantVariable (0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> ("Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.3.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable (1), 
+                                        "OffTime", ConstantVariable (0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds (1.0));
   ooff->Stop (Seconds (10.0));
 
   // Create a packet sink to receive these packets
   // The last argument "true" disables output from the Receive callback
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n3, 
-    InetSocketAddress (Ipv4Address::GetAny (), port), 
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> ("Node", n3, 
+                                  "Remote", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n3->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
   sink->Stop (Seconds (10.0));
 
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
-  ooff = CreateObject<OnOffApplication> (
-    n3, 
-    InetSocketAddress ("10.1.2.1", port),
-    "Udp",
-    ConstantVariable (1), 
-    ConstantVariable (0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n3, 
+                                             "Remote", Address (InetSocketAddress ("10.1.2.1", port)),
+                                             "Protocol", TypeId::LookupByName ("Udp"),
+                                             "OnTime", ConstantVariable (1), 
+                                             "OffTime", ConstantVariable (0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds (1.1));
   ooff->Stop (Seconds (10.0));
 
   // Create a packet sink to receive these packets
-  sink = CreateObject<PacketSink> (
-    n1, 
-    InetSocketAddress (Ipv4Address::GetAny (), port), 
-    "Udp");
+  sink = CreateObjectWith<PacketSink> ("Node", n1,
+                                       "Remote", Address (InetSocketAddress (Ipv4Address::GetAny (), port)), 
+                                       "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.1));
   sink->Stop (Seconds (10.0));
--- a/examples/simple-point-to-point-olsr.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/simple-point-to-point-olsr.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -43,6 +43,8 @@
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/config.h"
+#include "ns3/string.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -61,7 +63,7 @@
 #include "ns3/point-to-point-topology.h"
 #include "ns3/onoff-application.h"
 #include "ns3/packet-sink.h"
-#include "ns3/olsr.h"
+#include "ns3/olsr-helper.h"
 
 using namespace ns3;
 
@@ -98,16 +100,10 @@
   LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_ALL);
 #endif
 
-  // Set up some default values for the simulation.  Use the Bind()
-  // technique to tell the system what subclass of Queue to use,
-  // and what the queue limit is
+  // Set up some default values for the simulation.
 
-  // The below Bind command tells the queue factory which class to
-  // instantiate, when the queue factory is invoked in the topology code
-  DefaultValue::Bind ("Queue", "DropTailQueue");
-
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+  Config::SetDefault ("OnOffApplication::PacketSize", String ("210"));
+  Config::SetDefault ("OnOffApplication::DataRate", String ("448kb/s"));
 
   //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
 
@@ -162,45 +158,52 @@
 
   // Enable OLSR
   NS_LOG_INFO ("Enabling OLSR Routing.");
-  olsr::EnableAllNodes ();
+  OlsrHelper olsr;
+  olsr.EnableAll ();
 
 
   // Create the OnOff application to send UDP datagrams of size
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.4.2", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.4.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.0));
 
   // Create an optional packet sink to receive these packets
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n4,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n4,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n3->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
 
-  // Create a similar flow from n4 to n1, starting at time 1.1 seconds
-  ooff = CreateObject<OnOffApplication> (
-    n4, 
-    InetSocketAddress ("10.1.2.1", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  // Create a similar flow from n3 to n1, starting at time 1.1 seconds
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n4, 
+                                             "Remote", Address (InetSocketAddress ("10.1.2.1", port)), 
+                                             "Protocol", TypeId::LookupByName ("Udp"),
+                                             "OnTime", ConstantVariable(1), 
+                                             "OffTime", ConstantVariable(0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds(1.1));
 
   // Create a packet sink to receive these packets
-  sink = CreateObject<PacketSink> (
-    n1,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  sink = CreateObjectWith<PacketSink> (
+                                       "Node", n1,
+                                       "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                       "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.1));
 
--- a/examples/simple-point-to-point.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/simple-point-to-point.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -43,6 +43,8 @@
 #include "ns3/default-value.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
+#include "ns3/config.h"
+#include "ns3/string.h"
 
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
@@ -75,16 +77,10 @@
   LogComponentEnable ("SimplePointToPointExample", LOG_LEVEL_ALL);
 #endif
 
-  // Set up some default values for the simulation.  Use the Bind()
-  // technique to tell the system what subclass of Queue to use,
-  // and what the queue limit is
+  // Set up some default values for the simulation.
 
-  // The below Bind command tells the queue factory which class to
-  // instantiate, when the queue factory is invoked in the topology code
-  DefaultValue::Bind ("Queue", "DropTailQueue");
-
-  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
-  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+  Config::SetDefault ("OnOffApplication::PacketSize", String ("210"));
+  Config::SetDefault ("OnOffApplication::DataRate", String ("448kb/s"));
 
   // Allow the user to override any of the defaults and the above
   // Bind()s at run-time, via command-line arguments
@@ -139,38 +135,44 @@
   // 210 bytes at a rate of 448 Kb/s
   NS_LOG_INFO ("Create Applications.");
   uint16_t port = 9;   // Discard port (RFC 863)
-  Ptr<OnOffApplication> ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.3.2", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  Ptr<OnOffApplication> ooff = 
+    CreateObjectWith<OnOffApplication> (
+                                        "Node", n0, 
+                                        "Remote", Address (InetSocketAddress ("10.1.3.2", port)), 
+                                        "Protocol", TypeId::LookupByName ("Udp"),
+                                        "OnTime", ConstantVariable(1), 
+                                        "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds(1.0));
 
   // Create an optional packet sink to receive these packets
-  Ptr<PacketSink> sink = CreateObject<PacketSink> (
-    n3,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n3,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                  "Protocol", TypeId::LookupByName ("Udp"));
+  n3->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.0));
 
   // Create a similar flow from n3 to n1, starting at time 1.1 seconds
-  ooff = CreateObject<OnOffApplication> (
-    n3, 
-    InetSocketAddress ("10.1.2.1", port), 
-    "Udp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n3, 
+                                             "Remote", Address (InetSocketAddress ("10.1.2.1", port)), 
+                                             "Protocol", TypeId::LookupByName ("Udp"),
+                                             "OnTime", ConstantVariable(1), 
+                                             "OffTime", ConstantVariable(0));
+  n3->AddApplication (ooff);
   // Start the application
   ooff->Start(Seconds(1.1));
 
   // Create a packet sink to receive these packets
-  sink = CreateObject<PacketSink> (
-    n1,
-    InetSocketAddress (Ipv4Address::GetAny (), port),
-    "Udp");
+  sink = CreateObjectWith<PacketSink> (
+                                       "Node", n1,
+                                       "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), port)),
+                                       "Protocol", TypeId::LookupByName ("Udp"));
+  n1->AddApplication (sink);
   // Start the sink
   sink->Start (Seconds (1.1));
 
@@ -178,21 +180,23 @@
   // Create a file transfer from n0 to n3, starting at time 1.2
   uint16_t servPort = 500;
 
-  ooff = CreateObject<OnOffApplication> (
-    n0, 
-    InetSocketAddress ("10.1.3.2", servPort), 
-    "Tcp",
-    ConstantVariable(1), 
-    ConstantVariable(0));
+  ooff = CreateObjectWith<OnOffApplication> (
+                                             "Node", n0, 
+                                             "Remote", Address (InetSocketAddress ("10.1.3.2", servPort)), 
+                                             "Protocol", TypeId::LookupByName ("Tcp"),
+                                             "OnTime", ConstantVariable(1), 
+                                             "OffTime", ConstantVariable(0));
+  n0->AddApplication (ooff);
   // Start the application
   ooff->Start (Seconds(1.2));
   ooff->Stop (Seconds(1.35));
 
   // Create a packet sink to receive these TCP packets
-  sink = Create<PacketSink> (
-    n3,
-    InetSocketAddress (Ipv4Address::GetAny (), servPort),
-    "Tcp");
+  sink = CreateObjectWith<PacketSink> (
+                                       "Node", n3,
+                                       "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), servPort)),
+                                       "Protocol", TypeId::LookupByName ("Tcp"));
+  n3->AddApplication (sink);
   sink->Start (Seconds (1.2));
 
   // Here, finish off packet routing configuration
--- a/examples/tcp-large-transfer-errors.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/tcp-large-transfer-errors.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -196,10 +196,12 @@
   localSocket->Bind ();
 
   // Create a packet sink to receive these packets
-  Ptr<PacketSink> sink = Create<PacketSink> (
-    n2,
-    InetSocketAddress (Ipv4Address::GetAny (), servPort),
-    "Tcp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n2,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), servPort)),
+                                  "Protocol", TypeId::LookupByName ("Tcp"));
+  n2->AddApplication (sink);
   sink->Start (Seconds (0.0));
   sink->Stop (Seconds (10000.0));
 
--- a/examples/tcp-large-transfer.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/tcp-large-transfer.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -196,10 +196,12 @@
   localSocket->Bind ();
 
   // Create a packet sink to receive these packets
-  Ptr<PacketSink> sink = Create<PacketSink> (
-    n2,
-    InetSocketAddress (Ipv4Address::GetAny (), servPort),
-    "Tcp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n2,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), servPort)),
+                                  "Protocol", TypeId::LookupByName ("Tcp"));
+  n2->AddApplication (sink);
   sink->Start (Seconds (0.0));
   sink->Stop (Seconds (100.0));
 
--- a/examples/tcp-small-transfer-oneloss.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/tcp-small-transfer-oneloss.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -178,10 +178,12 @@
   localSocket->Bind ();
 
   // Create a packet sink to receive these packets
-  Ptr<PacketSink> sink = Create<PacketSink> (
-    n2,
-    InetSocketAddress (Ipv4Address::GetAny (), servPort),
-    "Tcp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n2,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), servPort)),
+                                  "Protocol", TypeId::LookupByName ("Tcp"));
+  n2->AddApplication (sink);
   sink->Start (Seconds (0.0));
   sink->Stop (Seconds (100.0));
 
--- a/examples/tcp-small-transfer.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/tcp-small-transfer.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -188,10 +188,12 @@
   localSocket->Bind ();
 
   // Create a packet sink to receive these packets
-  Ptr<PacketSink> sink = Create<PacketSink> (
-    n2,
-    InetSocketAddress (Ipv4Address::GetAny (), servPort),
-    "Tcp");
+  Ptr<PacketSink> sink = 
+    CreateObjectWith<PacketSink> (
+                                  "Node", n2,
+                                  "Local", Address (InetSocketAddress (Ipv4Address::GetAny (), servPort)),
+                                  "Protocol", TypeId::LookupByName ("Tcp"));
+  n2->AddApplication (sink);
   sink->Start (Seconds (0.0));
   sink->Stop (Seconds (100.0));
 
--- a/examples/udp-echo.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/examples/udp-echo.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -47,6 +47,7 @@
 #include "ns3/ipv4-route.h"
 #include "ns3/udp-echo-client.h"
 #include "ns3/udp-echo-server.h"
+#include "ns3/uinteger.h"
 
 using namespace ns3;
 
@@ -167,7 +168,9 @@
 //
   uint16_t port = 9;  // well-known echo port number
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                                               "Port", Uinteger (port));
+  n1->AddApplication (server);
 //
 // Create a UdpEchoClient application to send UDP datagrams from node zero to
 // node one.
@@ -176,8 +179,14 @@
   uint32_t maxPacketCount = 1;
   Time interPacketInterval = Seconds (1.);
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", port, 
-    maxPacketCount, interPacketInterval, packetSize);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port),
+                                     "MaxPackets", Uinteger (maxPacketCount), 
+                                     "Interval", interPacketInterval, 
+                                     "PacketSize", Uinteger (packetSize));
+  n0->AddApplication (client);
 //
 // Tell the applications when to start and stop.
 //
--- a/samples/main-adhoc-wifi.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/main-adhoc-wifi.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -33,6 +33,7 @@
 #include "ns3/socket-factory.h"
 #include "ns3/command-line.h"
 #include "ns3/gnuplot.h"
+#include "ns3/uinteger.h"
 
 
 #include <iostream>
@@ -47,6 +48,7 @@
 {
   Ptr<Node> node = CreateObject<Node> ();  
   Ptr<AdhocWifiNetDevice> device = CreateObject<AdhocWifiNetDevice> (node, Mac48Address (address));
+  node->AddDevice (device);
   device->Attach (channel);
   Ptr<MobilityModel> mobility = CreateObject<StaticMobilityModel> ();
   mobility->SetPosition (position);
@@ -121,12 +123,15 @@
   destination.SetProtocol (1);
   destination.SetSingleDevice (0);
   destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:02"));
-  Ptr<Application> app = CreateObject<OnOffApplication> (a, destination, 
-                                                   "Packet", 
-                                                   ConstantVariable (250),
-                                                   ConstantVariable (0),
-                                                   DataRate (60000000),
-                                                   2000);
+  Ptr<Application> app = 
+    CreateObjectWith<OnOffApplication> ("Node", a, 
+                                        "Remote", Address (destination),
+                                        "Protocol", TypeId::LookupByName ("Packet"),
+                                        "OnTime", ConstantVariable (250),
+                                        "OffTime", ConstantVariable (0),
+                                        "DataRate", DataRate (60000000),
+                                        "PacketSize", Uinteger (2000));
+  a->AddApplication (app);
 
   app->Start (Seconds (0.5));
   app->Stop (Seconds (250.0));
--- a/samples/main-ap-wifi.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/main-ap-wifi.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -73,6 +73,7 @@
 {
   Ptr<Node> node = CreateObject<Node> ();  
   Ptr<NqapWifiNetDevice> device = CreateObject<NqapWifiNetDevice> (node, Mac48Address (macAddress));
+  node->AddDevice (device);
   device->SetSsid (ssid);
   Simulator::Schedule (at, &NqapWifiNetDevice::StartBeaconing, device);
   device->Attach (channel);
@@ -90,6 +91,7 @@
 {
   Ptr<Node> node = CreateObject<Node> ();  
   Ptr<NqstaWifiNetDevice> device = CreateObject<NqstaWifiNetDevice> (node, Mac48Address (macAddress));
+  node->AddDevice (device);
   Simulator::ScheduleNow (&NqstaWifiNetDevice::StartActiveAssociation, device, 
                           ssid);
   device->Attach (channel);
@@ -170,10 +172,13 @@
   destination.SetProtocol (1);
   destination.SetSingleDevice (0);
   destination.SetPhysicalAddress (Mac48Address ("00:00:00:00:00:03"));
-  Ptr<Application> app = CreateObject<OnOffApplication> (b, destination, 
-                                                   "Packet", 
-                                                   ConstantVariable (42),
-                                                   ConstantVariable (0));
+  Ptr<Application> app = 
+    CreateObjectWith<OnOffApplication> ("Node", b, 
+                                        "Remote", Address (destination), 
+                                        "Protocol", TypeId::LookupByName ("Packet"),
+                                        "OnTime", ConstantVariable (42),
+                                        "OffTime", ConstantVariable (0));
+  b->AddApplication (app);
   app->Start (Seconds (0.5));
   app->Stop (Seconds (43.0));
 
--- a/samples/main-grid-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/main-grid-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -1,10 +1,13 @@
 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
 
 #include "ns3/ptr.h"
-#include "ns3/grid-topology.h"
-#include "ns3/static-mobility-model.h"
-#include "ns3/internet-node.h"
+#include "ns3/node.h"
 #include "ns3/command-line.h"
+#include "ns3/mobility-model.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/uinteger.h"
+#include "ns3/double.h"
+#include "ns3/string.h"
 
 using namespace ns3;
 
@@ -17,22 +20,30 @@
   // create an array of empty nodes for testing purposes 
   for (uint32_t i = 0; i < 120; i++)
     {
-      nodes.push_back (CreateObject<InternetNode> ());
+      nodes.push_back (CreateObject<Node> ());
     }
 
+  MobilityHelper mobility;
   // setup the grid itself: objects are layed out
   // started from (-100,-100) with 20 objects per row, 
   // the x interval between each object is 5 meters
   // and the y interval between each object is 20 meters
-  GridTopology grid (-100, -100, 20, 5, 20);
-
+  mobility.SetPositionAllocator ("GridPositionAllocator",
+                                 "MinX", Double (-100.0),
+                                 "MinY", Double (-100.0),
+                                 "DeltaX", Double (5.0),
+                                 "DeltaY", Double (20.0),
+                                 "GridWidth", Uinteger (20),
+                                 "LayoutType", String ("RowFirst"));
   // each object will be attached a static position.
-  grid.SetMobilityModel (StaticMobilityModel::GetTypeId ());
+  // i.e., once set by the "position allocator", the
+  // position will never change.
+  mobility.SetMobilityModel ("StaticMobilityModel");
 
   // finalize the setup by attaching to each object
   // in the input array a position and initializing
   // this position with the calculated coordinates.
-  grid.LayoutRowFirst (nodes.begin (), nodes.end ());
+  mobility.Layout (nodes.begin (), nodes.end ());
 
   // iterate our nodes and print their position.
   for (std::vector<Ptr<Object> >::const_iterator j = nodes.begin ();
--- a/samples/main-random-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/main-random-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -4,13 +4,14 @@
 
 #include "ns3/ptr.h"
 #include "ns3/mobility-model.h"
-#include "ns3/mobility-model-notifier.h"
-#include "ns3/static-mobility-model.h"
-#include "ns3/random-topology.h"
 #include "ns3/default-value.h"
 #include "ns3/command-line.h"
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
+#include "ns3/node.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/node-list.h"
+#include "ns3/string.h"
 
 using namespace ns3;
 
@@ -24,26 +25,27 @@
 
 int main (int argc, char *argv[])
 {
-  DefaultValue::Bind ("RandomDiscPositionX", "100");
-  DefaultValue::Bind ("RandomDiscPositionY", "50");
-  DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
-
-  DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
-  DefaultValue::Bind ("RandomTopologyMobilityType", "StaticMobilityModel");
 
   CommandLine::Parse (argc, argv);
 
-  RandomTopology topology;
 
   std::vector<Ptr<Object> > objects;
   for (uint32_t i = 0; i < 10000; i++)
     {
-      Ptr<MobilityModelNotifier> notifier = CreateObject<MobilityModelNotifier> ();
-      notifier->TraceConnect ("/course-change", MakeCallback (&CourseChange));
-      objects.push_back (notifier);
+      objects.push_back (CreateObject<Node> ());
     }
 
-  topology.Layout (objects.begin (), objects.end ());
+  MobilityHelper mobility;
+  mobility.EnableNotifier ();
+  mobility.SetPositionAllocator ("RandomDiscPositionAllocator",
+                                 "X", String ("100.0"),
+                                 "Y", String ("100.0"),
+                                 "Rho", String ("Uniform:0:30"));
+  mobility.SetMobilityModel ("StaticMobilityModel");
+  mobility.Layout (objects.begin (), objects.end ());
+
+  NodeList::Connect ("/nodes/*/$MobilityModelNotifier/course-change", 
+                     MakeCallback (&CourseChange));
 
   Simulator::StopAt (Seconds (100.0));
 
--- a/samples/main-random-walk.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/main-random-walk.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -4,14 +4,15 @@
 
 #include "ns3/ptr.h"
 #include "ns3/mobility-model.h"
-#include "ns3/mobility-model-notifier.h"
-#include "ns3/random-topology.h"
+#include "ns3/position-allocator.h"
 #include "ns3/default-value.h"
 #include "ns3/command-line.h"
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
 #include "ns3/node.h"
 #include "ns3/node-list.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/string.h"
 
 using namespace ns3;
 
@@ -32,24 +33,27 @@
   DefaultValue::Bind ("RandomWalk2dSpeed", "Constant:1.0");
   DefaultValue::Bind ("RandomWalk2dBounds", "0:200:0:100");
 
-  DefaultValue::Bind ("RandomDiscPositionX", "100");
-  DefaultValue::Bind ("RandomDiscPositionY", "50");
-  DefaultValue::Bind ("RandomDiscPositionRho", "Uniform:0:30");
-
-  DefaultValue::Bind ("RandomTopologyPositionType", "RandomDiscPosition");
   DefaultValue::Bind ("RandomTopologyMobilityType", "RandomWalk2dMobilityModel");
 
   CommandLine::Parse (argc, argv);
 
-  RandomTopology topology;
-
   for (uint32_t i = 0; i < 100; i++)
     {
       Ptr<Node> node = CreateObject<Node> ();
-      node->AggregateObject (CreateObject<MobilityModelNotifier> ());
     }
 
-  topology.Layout (NodeList::Begin (), NodeList::End ());
+  MobilityHelper mobility;
+  mobility.EnableNotifier ();
+  mobility.SetPositionAllocator ("RandomDiscPositionAllocator",
+                                 "X", String ("100.0"),
+                                 "Y", String ("100.0"),
+                                 "Rho", String ("Uniform:0:30"));
+  mobility.SetMobilityModel ("RandomWalk2dMobilityModel",
+                             "Mode", String ("Time"),
+                             "Time", String ("2s"),
+                             "Speed", String ("Constant:1.0"),
+                             "Bounds", String ("0:200:0:100"));
+  mobility.Layout (NodeList::Begin (), NodeList::End ());
   NodeList::Connect ("/nodes/*/$MobilityModelNotifier/course-change", 
                      MakeCallback (&CourseChange));
 
--- a/samples/wscript	Tue Feb 26 01:39:59 2008 +0100
+++ b/samples/wscript	Wed Feb 27 22:19:39 2008 +0100
@@ -4,9 +4,6 @@
     obj = bld.create_ns3_program('main-callback')
     obj.source = 'main-callback.cc'
 
-    obj = bld.create_ns3_program('main-ptr')
-    obj.source = 'main-ptr.cc'
-
     obj = bld.create_ns3_program('main-simulator')
     obj.source = 'main-simulator.cc'
 
--- a/src/applications/onoff/onoff-application.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/onoff/onoff-application.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -31,10 +31,11 @@
 #include "ns3/socket.h"
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
-#include "ns3/default-value.h"
 #include "ns3/packet.h"
-#include "ns3/composite-trace-resolver.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
 #include "onoff-application.h"
+#include "ns3/udp.h"
 
 NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
 
@@ -42,63 +43,54 @@
 
 namespace ns3 {
 
-// Defaults for rate/size
-static DataRateDefaultValue g_defaultRate ("OnOffApplicationDataRate", 
-                                           "The data rate in on state for OnOffApplication",
-                                           DataRate ("500kb/s"));
-static NumericDefaultValue<uint32_t> g_defaultSize ("OnOffApplicationPacketSize", 
-                                                    "The size of packets sent in on state for OnOffApplication",
-                                                    512, 1);
-// Constructors
+NS_OBJECT_ENSURE_REGISTERED (OnOffApplication);
 
-OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Address &remote,
-                                   std::string tid,
-                                   const  RandomVariable& ontime,
-                                   const  RandomVariable& offtime)
-  :  Application(n),
-     m_cbrRate (g_defaultRate.GetValue ())
+TypeId
+OnOffApplication::GetTypeId (void)
 {
-  Construct (n, remote, tid,
-             ontime, offtime, 
-             g_defaultSize.GetValue ());
+  static TypeId tid = TypeId ("OnOffApplication")
+    .SetParent<Application> ()
+    .AddConstructor<OnOffApplication> ()
+    .AddAttribute ("DataRate", "The data rate in on state.",
+                   DataRate ("500kb/s"),
+                   MakeDataRateAccessor (&OnOffApplication::m_cbrRate),
+                   MakeDataRateChecker ())
+    .AddAttribute ("PacketSize", "The size of packets sent in on state",
+                   Uinteger (512),
+                   MakeUintegerAccessor (&OnOffApplication::m_pktSize),
+                   MakeUintegerChecker<uint32_t> (1))
+    .AddAttribute ("Remote", "The address of the destination",
+                   Address (),
+                   MakeAddressAccessor (&OnOffApplication::m_peer),
+                   MakeAddressChecker ())
+    .AddAttribute ("OnTime", "A RandomVariable used to pick the duration of the 'On' state.",
+                   ConstantVariable (1.0),
+                   MakeRandomVariableAccessor (&OnOffApplication::m_onTime),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("OffTime", "A RandomVariable used to pick the duration of the 'Off' state.",
+                   ConstantVariable (1.0),
+                   MakeRandomVariableAccessor (&OnOffApplication::m_offTime),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("Protocol", "The type of protocol to use.",
+                   Udp::GetTypeId (),
+                   MakeTypeIdAccessor (&OnOffApplication::m_tid),
+                   MakeTypeIdChecker ())
+    .AddTraceSource ("Tx", "A new packet is created and is sent",
+                     MakeTraceSourceAccessor (&OnOffApplication::m_txTrace))
+    ;
+  return tid;
 }
 
-OnOffApplication::OnOffApplication(Ptr<Node> n, 
-                                   const Address &remote,
-                                   std::string tid,
-                                   const  RandomVariable& ontime,
-                                   const  RandomVariable& offtime,
-                                   DataRate  rate,
-                                   uint32_t size)
-  :  Application(n),
-     m_cbrRate (rate)
+
+OnOffApplication::OnOffApplication ()
 {
   NS_LOG_FUNCTION;
-  Construct (n, remote, tid, ontime, offtime, size);
-}
-
-void
-OnOffApplication::Construct (Ptr<Node> n, 
-                             const Address &remote,
-                             std::string tid,
-                             const  RandomVariable& onTime,
-                             const  RandomVariable& offTime,
-                             uint32_t size)
-{
-  NS_LOG_FUNCTION;
-
   m_socket = 0;
-  m_peer = remote;
   m_connected = false;
-  m_onTime = onTime;
-  m_offTime = offTime;
-  m_pktSize = size;
   m_residualBits = 0;
   m_lastStartTime = Seconds (0);
   m_maxBytes = 0;
   m_totBytes = 0;
-  m_tid = tid;
 }
 
 OnOffApplication::~OnOffApplication()
@@ -114,21 +106,6 @@
   m_maxBytes = maxBytes;
 }
 
-void
-OnOffApplication::SetDefaultRate (const DataRate &rate)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (&rate);
-  g_defaultRate.SetValue (rate);
-}
-
-void 
-OnOffApplication::SetDefaultSize (uint32_t size)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (size);
-  g_defaultSize.SetValue (size);
-}
 
 void
 OnOffApplication::DoDispose (void)
@@ -148,8 +125,7 @@
   // Create the socket if not already
   if (!m_socket)
     {
-      TypeId tid = TypeId::LookupByName (m_tid);
-      Ptr<SocketFactory> socketFactory = GetNode ()->GetObject<SocketFactory> (tid);
+      Ptr<SocketFactory> socketFactory = GetNode ()->GetObject<SocketFactory> (m_tid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind ();
       m_socket->Connect (m_peer);
@@ -189,7 +165,6 @@
   NS_LOG_FUNCTION;
 
   Simulator::Cancel(m_sendEvent);
-  m_socket->Close ();
 }
 
 // Private helpers
@@ -259,17 +234,4 @@
   cout << "OnOffApplication, Connection Failed" << endl;
 }
 
-Ptr<TraceResolver> 
-OnOffApplication::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddSource ("tx",
-                       TraceDoc ("A new packet is created and is sent",
-                                 "Ptr<const Packet>",
-                                 "The newly-created packet."),
-                       m_txTrace);
-  resolver->SetParentResolver (Application::GetTraceResolver ());
-  return resolver;
-}
-
 } // Namespace ns3
--- a/src/applications/onoff/onoff-application.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/onoff/onoff-application.h	Wed Feb 27 22:19:39 2008 +0100
@@ -29,8 +29,8 @@
 #include "ns3/event-id.h"
 #include "ns3/ptr.h"
 #include "ns3/data-rate.h"
-#include "ns3/callback-trace-source.h"
 #include "ns3/random-variable.h"
+#include "ns3/traced-callback.h"
 
 namespace ns3 {
 
@@ -52,60 +52,14 @@
 class OnOffApplication : public Application 
 {
 public:
-  /**
-   * \param n node associated to this application
-   * \param remote remote ip address
-   * \param tid  TypeId of the socket factory to use. Note this
-   * factory should create sockets compatible with the specified
-   * remote address.
-   * \param ontime on time random variable
-   * \param offtime off time random variable
-   */
-  OnOffApplication(Ptr<Node> n,
-                   const Address &remote,
-                   std::string tid,
-                   const RandomVariable& ontime,
-                   const RandomVariable& offtime);
+  static TypeId GetTypeId (void);
 
-  /**
-   * \param n node associated to this application
-   * \param remote remote ip address
-   * \param tid  TypeId of the socket factory to use. Note this
-   * factory should create sockets compatible with the specified
-   * remote address.
-   * \param ontime on time random variable
-   * \param offtime off time random variable
-   * \param rate data rate when on
-   * \param size size of packets when sending data.
-   */
-  OnOffApplication(Ptr<Node> n,
-                   const Address &remote,
-                   std::string tid,
-                   const RandomVariable& ontime,
-                   const RandomVariable& offtime,
-                   DataRate  rate,
-                   uint32_t size);
+  OnOffApplication ();
 
   virtual ~OnOffApplication();
 
   void SetMaxBytes(uint32_t maxBytes);
 
-  /**
-   * \param r the data rate
-   *
-   * Set the data rate to use for every OnOffApplication for which
-   * the user does not specify an explicit data rate.
-   */
-  static void SetDefaultRate(const DataRate & r);
-
-  /**
-   * \param size the packet size
-   *
-   * Set the packet size to use for every OnOffApplication for
-   * which the user does not specify an explicit packet size.
-   */
-  static void SetDefaultSize (uint32_t size);
-
 protected:
   virtual void DoDispose (void);
 private:
@@ -129,8 +83,8 @@
   Ptr<Socket>     m_socket;       // Associated socket
   Address         m_peer;         // Peer address
   bool            m_connected;    // True if connected
-  RandomVariable m_onTime;       // rng for On Time
-  RandomVariable m_offTime;      // rng for Off Time
+  RandomVariable  m_onTime;       // rng for On Time
+  RandomVariable  m_offTime;      // rng for Off Time
   DataRate        m_cbrRate;      // Rate that data is generated
   uint32_t        m_pktSize;      // Size of packets
   uint32_t        m_residualBits; // Number of generated, but not sent, bits
@@ -140,11 +94,10 @@
   EventId         m_startStopEvent;     // Event id for next start or stop event
   EventId         m_sendEvent;    // Eventid of pending "send packet" event
   bool            m_sending;      // True if currently in sending state
-  std::string     m_tid;
-  CallbackTraceSource<Ptr<const Packet> > m_txTrace;
+  TypeId          m_tid;
+  TracedCallback<Ptr<const Packet> > m_txTrace;
   
 private:
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   void ScheduleNextTx();
   void ScheduleStartEvent();
   void ScheduleStopEvent();
--- a/src/applications/packet-sink/packet-sink.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/packet-sink/packet-sink.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -25,7 +25,8 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
-#include "ns3/composite-trace-resolver.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/udp.h"
 #include "packet-sink.h"
 
 using namespace std;
@@ -33,25 +34,30 @@
 namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("PacketSinkApplication");
-
-// Constructors
+NS_OBJECT_ENSURE_REGISTERED (PacketSink);
 
-PacketSink::PacketSink (Ptr<Node> n, 
-                        const Address &local,
-                        std::string tid)
-  :  Application(n)
+TypeId 
+PacketSink::GetTypeId (void)
 {
-  Construct (n, local, tid);
+  static TypeId tid = TypeId ("PacketSink")
+    .SetParent<Application> ()
+    .AddAttribute ("Local", "The Address on which to Bind the rx socket.",
+                   Address (),
+                   MakeAddressAccessor (&PacketSink::m_local),
+                   MakeAddressChecker ())
+    .AddAttribute ("Protocol", "The type id of the protocol to use for the rx socket.",
+                   Udp::GetTypeId (),
+                   MakeTypeIdAccessor (&PacketSink::m_tid),
+                   MakeTypeIdChecker ())
+    .AddTraceSource ("Rx", "A packet has been received",
+                     MakeTraceSourceAccessor (&PacketSink::m_rxTrace))
+    ;
+  return tid;
 }
 
-void
-PacketSink::Construct (Ptr<Node> n, 
-                       const Address &local,
-                       std::string tid)
+PacketSink::PacketSink ()
 {
   m_socket = 0;
-  m_local = local;
-  m_tid = tid;
 }
 
 PacketSink::~PacketSink()
@@ -73,9 +79,8 @@
   // Create the socket if not already
   if (!m_socket)
     {
-      TypeId tid = TypeId::LookupByName (m_tid);
       Ptr<SocketFactory> socketFactory = 
-        GetNode ()->GetObject<SocketFactory> (tid);
+        GetNode ()->GetObject<SocketFactory> (m_tid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind (m_local);
       m_socket->Listen (0);
@@ -116,19 +121,4 @@
   socket->Close ();
 }
 
-Ptr<TraceResolver> 
-PacketSink::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddSource ("rx",
-                       TraceDoc ("A new packet has been received",
-                                 "Ptr<const Packet>",
-                                 "The newly-received packet.",
-                                 "const Address &",
-                                 "The source address of the received packet."),
-                       m_rxTrace);
-  resolver->SetParentResolver (Application::GetTraceResolver ());
-  return resolver;
-}
-
 } // Namespace ns3
--- a/src/applications/packet-sink/packet-sink.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/packet-sink/packet-sink.h	Wed Feb 27 22:19:39 2008 +0100
@@ -24,7 +24,7 @@
 #include "ns3/application.h"
 #include "ns3/event-id.h"
 #include "ns3/ptr.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 #include "ns3/address.h"
 
 namespace ns3 {
@@ -53,14 +53,13 @@
 class PacketSink : public Application 
 {
 public:
+  static TypeId GetTypeId (void);
   /**
    * \param n node associated to this application
    * \param local local address to bind to
    * \param tid string to identify transport protocol of interest
    */
-  PacketSink (Ptr<Node> n,
-              const Address &local,
-              std::string tid);
+  PacketSink ();
 
   virtual ~PacketSink ();
 
@@ -70,20 +69,14 @@
   // inherited from Application base class.
   virtual void StartApplication (void);    // Called at time specified by Start
   virtual void StopApplication (void);     // Called at time specified by Stop
-  // inherited from Object base class.
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-
-  void Construct (Ptr<Node> n,
-                  const Address &local,
-                  std::string tid);
 
   virtual void Receive (Ptr<Socket> socket, Ptr<Packet> packet, const Address& from);
   virtual void CloseConnection (Ptr<Socket> socket);
 
   Ptr<Socket>     m_socket;       // Associated socket
   Address         m_local;        // Local address to bind to
-  std::string     m_tid;          // Protocol name (e.g., "Udp")
-  CallbackTraceSource<Ptr<const Packet>, const Address &> m_rxTrace;
+  TypeId          m_tid;          // Protocol TypeId
+  TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace;
   
 };
 
--- a/src/applications/udp-echo/udp-echo-client.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/udp-echo/udp-echo-client.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,27 +23,50 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
+#include "ns3/uinteger.h"
 #include "udp-echo-client.h"
 
 namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("UdpEchoClientApplication");
+NS_OBJECT_ENSURE_REGISTERED (UdpEchoClient);
 
-UdpEchoClient::UdpEchoClient (
-  Ptr<Node> n,
-  Ipv4Address serverAddress,
-  uint16_t serverPort,
-  uint32_t count,
-  Time interval,
-  uint32_t size)
-: 
-  Application(n)
+TypeId
+UdpEchoClient::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("UdpEchoClient")
+    .SetParent<Application> ()
+    .AddConstructor<UdpEchoClient> ()
+    .AddAttribute ("MaxPackets", "XXX",
+                   Uinteger (100),
+                   MakeUintegerAccessor (&UdpEchoClient::m_count),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("Interval", "XXX",
+                   Seconds (1.0),
+                   MakeTimeAccessor (&UdpEchoClient::m_interval),
+                   MakeTimeChecker ())
+    .AddAttribute ("RemoteIpv4", "XXX",
+                   Ipv4Address (),
+                   MakeIpv4AddressAccessor (&UdpEchoClient::m_peerAddress),
+                   MakeIpv4AddressChecker ())
+    .AddAttribute ("RemotePort", "XXX",
+                   Uinteger (0),
+                   MakeUintegerAccessor (&UdpEchoClient::m_peerPort),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("PacketSize", "Size of packets generated",
+                   Uinteger (100),
+                   MakeUintegerAccessor (&UdpEchoClient::m_size),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  return tid;
+}
+
+UdpEchoClient::UdpEchoClient ()
 {
   NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << n << serverAddress << serverPort << count
-                 << interval << size);
-
-  Construct (n, serverAddress, serverPort, count, interval, size);
+  m_sent = 0;
+  m_socket = 0;
+  m_sendEvent = EventId ();
 }
 
 UdpEchoClient::~UdpEchoClient()
@@ -52,32 +75,6 @@
 }
 
 void
-UdpEchoClient::Construct (
-  Ptr<Node> n,
-  Ipv4Address serverAddress,
-  uint16_t serverPort,
-  uint32_t count,
-  Time interval,
-  uint32_t size)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << n << serverAddress << serverPort
-                 << count << interval << size);
-
-  m_node = n;
-  m_serverAddress = serverAddress;
-  m_serverPort = serverPort;
-  m_count = count;
-  m_interval = interval;
-  m_size = size;
-
-  m_sent = 0;
-  m_socket = 0;
-  m_peer = InetSocketAddress (serverAddress, serverPort);
-  m_sendEvent = EventId ();
-}
-
-void
 UdpEchoClient::DoDispose (void)
 {
   NS_LOG_FUNCTION;
@@ -96,7 +93,7 @@
         GetNode ()->GetObject<SocketFactory> (tid);
       m_socket = socketFactory->CreateSocket ();
       m_socket->Bind ();
-      m_socket->Connect (m_peer);
+      m_socket->Connect (InetSocketAddress (m_peerAddress, m_peerPort));
     }
 
   m_socket->SetRecvCallback(MakeCallback(&UdpEchoClient::Receive, this));
@@ -136,7 +133,7 @@
   m_socket->Send (p);
   ++m_sent;
 
-  NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_serverAddress);
+  NS_LOG_INFO ("Sent " << m_size << " bytes to " << m_peerAddress);
 
   if (m_sent < m_count) 
     {
--- a/src/applications/udp-echo/udp-echo-client.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/udp-echo/udp-echo-client.h	Wed Feb 27 22:19:39 2008 +0100
@@ -32,8 +32,9 @@
 class UdpEchoClient : public Application 
 {
 public:
-  UdpEchoClient (Ptr<Node> n, Ipv4Address serverAddr, uint16_t serverPort,
-    uint32_t count, Time interval, uint32_t size);
+  static TypeId GetTypeId (void);
+
+  UdpEchoClient ();
 
   virtual ~UdpEchoClient ();
 
@@ -41,8 +42,6 @@
   virtual void DoDispose (void);
 
 private:
-  void Construct (Ptr<Node> n, Ipv4Address serverAddr, uint16_t serverPort,
-    uint32_t count, Time interval, uint32_t size);
 
   virtual void StartApplication (void);
   virtual void StopApplication (void);
@@ -52,16 +51,14 @@
 
   void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
 
-  Ptr<Node> m_node;
-  Ipv4Address m_serverAddress;
-  uint16_t m_serverPort;
   uint32_t m_count;
   Time m_interval;
   uint32_t m_size;
 
   uint32_t m_sent;
   Ptr<Socket> m_socket;
-  Address m_peer;
+  Ipv4Address m_peerAddress;
+  uint16_t m_peerPort;
   EventId m_sendEvent;
 
 };
--- a/src/applications/udp-echo/udp-echo-server.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/udp-echo/udp-echo-server.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -24,23 +24,32 @@
 #include "ns3/simulator.h"
 #include "ns3/socket-factory.h"
 #include "ns3/packet.h"
+#include "ns3/uinteger.h"
 
 #include "udp-echo-server.h"
 
 namespace ns3 {
 
 NS_LOG_COMPONENT_DEFINE ("UdpEchoServerApplication");
+NS_OBJECT_ENSURE_REGISTERED (UdpEchoServer);
 
-UdpEchoServer::UdpEchoServer (
-  Ptr<Node> n,
-  uint16_t port)
-: 
-  Application(n)
+TypeId
+UdpEchoServer::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("UdpEchoServer")
+    .SetParent<Application> ()
+    .AddConstructor<UdpEchoServer> ()
+    .AddAttribute ("Port", "Client Port",
+                   Uinteger (0),
+                   MakeUintegerAccessor (&UdpEchoServer::m_port),
+                   MakeUintegerChecker<uint16_t> ())
+    ;
+  return tid;
+}
+
+UdpEchoServer::UdpEchoServer ()
 {
   NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << n << port);
-
-  Construct (n, port);
 }
 
 UdpEchoServer::~UdpEchoServer()
@@ -49,21 +58,6 @@
 }
 
 void
-UdpEchoServer::Construct (
-  Ptr<Node> n,
-  uint16_t port)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << n << port);
-
-  m_node = n;
-  m_port = port;
-
-  m_socket = 0;
-  m_local = InetSocketAddress (Ipv4Address::GetAny (), port);
-}
-
-void
 UdpEchoServer::DoDispose (void)
 {
   NS_LOG_FUNCTION;
@@ -81,7 +75,8 @@
       Ptr<SocketFactory> socketFactory = 
         GetNode ()->GetObject<SocketFactory> (tid);
       m_socket = socketFactory->CreateSocket ();
-      m_socket->Bind (m_local);
+      InetSocketAddress local = InetSocketAddress (Ipv4Address::GetAny (), m_port);
+      m_socket->Bind (local);
     }
 
   m_socket->SetRecvCallback(MakeCallback(&UdpEchoServer::Receive, this));
--- a/src/applications/udp-echo/udp-echo-server.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/applications/udp-echo/udp-echo-server.h	Wed Feb 27 22:19:39 2008 +0100
@@ -32,23 +32,21 @@
 class UdpEchoServer : public Application 
 {
 public:
-  UdpEchoServer (Ptr<Node> n, uint16_t clientPort);
+  static TypeId GetTypeId (void);
+  UdpEchoServer ();
   virtual ~UdpEchoServer ();
 
 protected:
   virtual void DoDispose (void);
 
 private:
-  void Construct (Ptr<Node> n, uint16_t clientPort);
 
   virtual void StartApplication (void);
   virtual void StopApplication (void);
 
   void Receive(Ptr<Socket> socket, Ptr<Packet> packet, const Address &from);
 
-  Ptr<Node> m_node;
   uint16_t m_port;
-
   Ptr<Socket> m_socket;
   Address m_local;
 };
--- a/src/common/data-rate.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/common/data-rate.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -125,25 +125,15 @@
 
 namespace ns3 {
 
+VALUE_HELPER_CPP (DataRate);
+
+DataRate::DataRate ()
+  : m_bps (0)
+{}
+
 DataRate::DataRate(uint64_t bps)
   :m_bps(bps)
-{
-}
-
-DataRate::DataRate (const std::string s)
-  : m_bps(DataRate::Parse(s))
-{
-}
-
-uint64_t DataRate::Parse(const std::string s)
-{
-  uint64_t v;
-  if (!DoParse (s, &v))
-    {
-      NS_FATAL_ERROR("Can't Parse data rate "<<s);
-    }
-  return v;
-}
+{}
 
 bool DataRate::operator < (const DataRate& rhs) const
 {
@@ -185,6 +175,36 @@
   return m_bps;
 }
 
+DataRate::DataRate (std::string rate)
+{
+  bool ok = DoParse (rate, &m_bps);
+  if (!ok)
+    {
+      NS_FATAL_ERROR ("Could not parse rate: "<<rate);
+    }
+}
+
+std::ostream &operator << (std::ostream &os, const DataRate &rate)
+{
+  os << rate.GetBitRate () << "bps";
+  return os;
+}
+std::istream &operator >> (std::istream &is, DataRate &rate)
+{
+  std::string value;
+  is >> value;
+  uint64_t v;
+  bool ok = DoParse (value, &v);
+  if (!ok)
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  rate = DataRate (v);
+  return is;
+}
+
+
+
 double operator*(const DataRate& lhs, const Time& rhs)
 {
   return rhs.GetSeconds()*lhs.GetBitRate();
--- a/src/common/data-rate.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/common/data-rate.h	Wed Feb 27 22:19:39 2008 +0100
@@ -27,6 +27,8 @@
 #include <stdint.h>
 #include "ns3/nstime.h"
 #include "ns3/default-value.h"
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
 
 namespace ns3 {
 
@@ -46,7 +48,8 @@
  */
 class DataRate
 {
-  public:
+public:
+  DataRate ();
   /**
    * \brief Integer constructor
    *
@@ -55,23 +58,8 @@
    * non-trivial bitrate availiable.
    */
   DataRate (uint64_t bps);
-  
-  /**
-   * \brief String constructor
-   *
-   * Construct a DataRate from a string.  The supported strings have a 
-   * numerical portion, followed by units in the following format:
-   * - Prefix: nothing, "k", "M", "G"
-   * - Data Unit: "b, "B"
-   * - Time Suffix: "ps", "/s" \n
-   * The prefixes are SI powers of 10 (10^0,10^3,10^6,10^9 respectively).\n
-   * The units are the bit, and the (8-bit) byte respectively.\n
-   * Both time suffixes denote "per second".  Some supported examples include
-   * "20B/s", "56kbps", "4.4MB/s", and "100Gb/s".  Any malformed string causes
-   * a fatal error.
-   */
-  DataRate (const std::string s);
-  
+  DataRate (std::string rate);
+    
   bool operator <  (const DataRate& rhs) const;
   bool operator <= (const DataRate& rhs) const;
   bool operator >  (const DataRate& rhs) const;
@@ -93,11 +81,18 @@
    * \return The underlying bitrate in bits per second
    */
   uint64_t GetBitRate() const;
-  
-  private:
+
+  VALUE_HELPER_HEADER_1 (DataRate);
+private:
   uint64_t m_bps;
   static uint64_t Parse(const std::string);
 };
+
+std::ostream &operator << (std::ostream &os, const DataRate &rate);
+std::istream &operator >> (std::istream &is, DataRate &rate);
+
+VALUE_HELPER_HEADER_2 (DataRate);
+
 /**
  * \param lhs
  * \param rhs
@@ -122,6 +117,6 @@
   DataRate m_value;
 };
 
-};//namespace ns3
+} //namespace ns3
 
 #endif /* DATA_RATE_H */
--- a/src/common/error-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/common/error-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -27,24 +27,25 @@
 #include "ns3/assert.h"
 #include "ns3/log.h"
 #include "ns3/random-variable.h"
-#include "ns3/default-value.h"
-#include "ns3/type-id-default-value.h"
+#include "ns3/boolean.h"
+#include "ns3/enum.h"
+#include "ns3/double.h"
 
 NS_LOG_COMPONENT_DEFINE ("ErrorModel");
 
 namespace ns3 {
 
-static TypeIdDefaultValue g_interfaceIdErrorModelDefaultValue ("ErrorModel",
-                                                                    "Error Model", 
-                                                                    ErrorModel::GetTypeId (), 
-                                                                    "RateErrorModel");
-
 NS_OBJECT_ENSURE_REGISTERED (ErrorModel);
 
 TypeId ErrorModel::GetTypeId (void)
 { 
   static TypeId tid = TypeId ("ErrorModel")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("IsEnabled", "Whether this ErrorModel is enabled or not.",
+                   Boolean (true),
+                   MakeBooleanAccessor (&ErrorModel::m_enable),
+                   MakeBooleanChecker ())
+    ;
   return tid;
 }
 
@@ -59,15 +60,6 @@
   NS_LOG_FUNCTION;  
 }
 
-Ptr<ErrorModel>
-ErrorModel::CreateDefault (void)
-{ 
-  NS_LOG_FUNCTION;
-  TypeId interfaceId = g_interfaceIdErrorModelDefaultValue.GetValue ();
-  Ptr<ErrorModel> em = interfaceId.CreateObject ()->GetObject<ErrorModel> ();
-  return em;
-}
-
 bool
 ErrorModel::IsCorrupt (Ptr<Packet> p)
 {
@@ -111,36 +103,35 @@
 // RateErrorModel
 //
 
-// Defaults for rate/size
-static NumericDefaultValue<double> g_defaultRateErrorModelErrorRate
-  ("RateErrorModelErrorRate", "The error rate for the error model", 0.0);
-
-static EnumDefaultValue<enum ErrorUnit> 
- g_defaultRateErrorModelErrorUnit ("RateErrorModelErrorUnit", 
- "The error unit for this error model",
-    EU_BYTE, "EU_BYTE",
-    EU_PKT, "EU_PKT",
-    EU_BIT, "EU_BIT", 
-    0, (void*)0);
-
 NS_OBJECT_ENSURE_REGISTERED (RateErrorModel);
 
 TypeId RateErrorModel::GetTypeId (void)
 { 
   static TypeId tid = TypeId ("RateErrorModel")
     .SetParent<ErrorModel> ()
-    .AddConstructor<RateErrorModel> ();
+    .AddConstructor<RateErrorModel> ()
+    .AddAttribute ("ErrorUnit", "The error unit",
+                   Enum (EU_BYTE),
+                   MakeEnumAccessor (&RateErrorModel::m_unit),
+                   MakeEnumChecker (EU_BYTE, "EU_BYTE",
+                                    EU_PKT, "EU_PKT",
+                                    EU_BIT, "EU_BIT"))
+    .AddAttribute ("ErrorRate", "The error rate.",
+                   Double (0.0),
+                   MakeDoubleAccessor (&RateErrorModel::m_rate),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("RanVar", "The decision variable attached to this error model.",
+                   UniformVariable (0.0, 1.0),
+                   MakeRandomVariableAccessor (&RateErrorModel::m_ranvar),
+                   MakeRandomVariableChecker ())
+    ;
   return tid;
 }
 
 
-RateErrorModel::RateErrorModel () : 
-  m_unit (g_defaultRateErrorModelErrorUnit.GetValue() ),
-  m_rate (g_defaultRateErrorModelErrorRate.GetValue() )
+RateErrorModel::RateErrorModel ()
 {
   NS_LOG_FUNCTION;
-  // Assume a uniform random variable if user does not specify
-  m_ranvar = UniformVariable ();
 }
 
 RateErrorModel::~RateErrorModel () 
@@ -248,7 +239,8 @@
 { 
   static TypeId tid = TypeId ("ListErrorModel")
     .SetParent<ErrorModel> ()
-    .AddConstructor<ListErrorModel> ();
+    .AddConstructor<ListErrorModel> ()
+    ;
   return tid;
 }
 
--- a/src/common/packet.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/common/packet.h	Wed Feb 27 22:19:39 2008 +0100
@@ -31,6 +31,7 @@
 #include "ns3/callback.h"
 #include "ns3/assert.h"
 #include "ns3/ptr.h"
+#include "ns3/object-base.h"
 
 namespace ns3 {
 
@@ -73,7 +74,7 @@
  * The performance aspects of the Packet API are discussed in 
  * \ref packetperf
  */
-class Packet {
+class Packet : public ObjectBase {
 public:
   void Ref (void) const;
   void Unref (void) const;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/attribute-accessor-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,192 @@
+#ifndef ATTRIBUTE_ACCESSOR_HELPER_H
+#define ATTRIBUTE_ACCESSOR_HELPER_H
+
+namespace ns3 {
+
+template <typename V, typename T1>
+Ptr<const AttributeAccessor>
+MakeAccessorHelper (T1 a1);
+
+template <typename V, typename T1, typename T2>
+Ptr<const AttributeAccessor>
+MakeAccessorHelper (T1 a1, T2 a2);
+
+} // namespace ns3
+
+/***************************************************************
+ *        The implementation of the above functions.
+ ***************************************************************/
+
+#include "type-traits.h"
+
+namespace ns3 {
+
+template <typename T, typename U>
+class AccessorHelper : public AttributeAccessor
+{
+public:
+  AccessorHelper () {}
+
+  virtual bool Set (ObjectBase * object, Attribute val) const {
+    const U *value = val.DynCast<const U*> ();
+    if (value == 0)
+      {
+	return false;
+      }
+    T *obj = dynamic_cast<T *> (object);
+    if (obj == 0)
+      {
+	return false;
+      }
+    return DoSet (obj, value);
+  }
+
+  virtual bool Get (const ObjectBase * object, Attribute val) const {
+    U *value = val.DynCast<U*> ();
+    if (value == 0)
+      {
+	return false;
+      }
+    const T *obj = dynamic_cast<const T *> (object);
+    if (obj == 0)
+      {
+	return false;
+      }
+    return DoGet (obj, value);
+  }
+
+
+private:
+  virtual bool DoSet (T *object, const U *v) const = 0;
+  virtual bool DoGet (const T *object, U *v) const = 0;
+};
+
+template <typename V, typename T, typename U>
+Ptr<const AttributeAccessor>
+DoMakeAccessorHelperOne (U T::*memberVariable)
+{
+  class MemberVariable : public AccessorHelper<T,V>
+    {
+    public:
+      MemberVariable (U T::*memberVariable)
+	: AccessorHelper<T,V> (),
+	m_memberVariable (memberVariable)
+	{}
+    private:
+      virtual bool DoSet (T *object, const V *v) const {
+	(object->*m_memberVariable) = U (v->Get ());
+	return true;
+      }
+      virtual bool DoGet (const T *object, V *v) const {
+	v->Set (object->*m_memberVariable);
+	return true;
+      }
+      
+      U T::*m_memberVariable;
+    };
+  return Ptr<const AttributeAccessor> (new MemberVariable (memberVariable), false);
+}
+
+template <typename V, typename T, typename U>
+Ptr<const AttributeAccessor>
+DoMakeAccessorHelperOne (U (T::*getter) (void) const)
+{
+  class MemberMethod : public AccessorHelper<T,V>
+    {
+    public:
+      MemberMethod (U (T::*getter) (void) const)
+	: AccessorHelper<T,V> (),
+	m_getter (getter)
+	{}
+    private:
+      virtual bool DoSet (T *object, const V *v) const {
+	return false;
+      }
+      virtual bool DoGet (const T *object, V *v) const {
+	v->Set ((object->*m_getter) ());
+	return true;
+      }
+      U (T::*m_getter) (void) const;
+    };
+  return Ptr<const AttributeAccessor> (new MemberMethod (getter), false);
+}
+
+
+template <typename V, typename T, typename U>
+Ptr<const AttributeAccessor>
+DoMakeAccessorHelperOne (void (T::*setter) (U))
+{
+  class MemberMethod : public AccessorHelper<T,V>
+    {
+    public:
+      MemberMethod (void (T::*setter) (U))
+	: AccessorHelper<T,V> (),
+	m_setter (setter)
+	{}
+    private:
+      virtual bool DoSet (T *object, const V *v) const {
+	(object->*m_setter) (v->Get ());
+	return true;
+      }
+      virtual void DoGet (const T *object, V *v) const {
+	return false;
+      }
+      void (T::*m_setter) (U);
+    };
+  return Ptr<const AttributeAccessor> (new MemberMethod (setter), false);
+}
+
+template <typename W, typename T, typename U, typename V>
+Ptr<const AttributeAccessor>
+DoMakeAccessorHelperTwo (void (T::*setter) (U), 
+			  V (T::*getter) (void) const)
+{
+  class MemberMethod : public AccessorHelper<T,W>
+    {
+    public:
+      MemberMethod (void (T::*setter) (U), 
+		    V (T::*getter) (void) const)
+	: AccessorHelper<T,W> (),
+	m_setter (setter),
+	m_getter (getter)
+	{}
+    private:
+      virtual bool DoSet (T *object, const W *v) const {
+	(object->*m_setter) (v->Get ());
+	return true;
+      }
+      virtual bool DoGet (const T *object, W *v) const {
+	v->Set ((object->*m_getter) ());
+	return true;
+      }
+      void (T::*m_setter) (U);
+      V (T::*m_getter) (void) const;
+    };
+  return Ptr<const AttributeAccessor> (new MemberMethod (setter, getter), false);
+}
+
+template <typename W, typename T, typename U, typename V>
+Ptr<const AttributeAccessor>
+DoMakeAccessorHelperTwo (V (T::*getter) (void) const, 
+			  void (T::*setter) (U))
+{
+  return DoMakeAccessorHelperTwo<W> (setter, getter);
+}
+
+template <typename V, typename T1>
+Ptr<const AttributeAccessor>
+MakeAccessorHelper (T1 a1)
+{
+  return DoMakeAccessorHelperOne<V> (a1);
+}
+
+template <typename V, typename T1, typename T2>
+Ptr<const AttributeAccessor>
+MakeAccessorHelper (T1 a1, T2 a2)
+{
+  return DoMakeAccessorHelperTwo<V> (a1, a2);
+}
+
+} // namespace ns3
+
+#endif /* ATTRIBUTE_ACCESSOR_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/attribute-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,123 @@
+#ifndef VALUE_HELPER_H
+#define VALUE_HELPER_H
+
+#include "attribute.h"
+#include "object-base.h"
+#include "attribute-accessor-helper.h"
+#include <sstream>
+#include "fatal-error.h"
+
+#define ATTRIBUTE_ACCESSOR_DEFINE(type)					\
+  template <typename T1>						\
+  Ptr<const AttributeAccessor> Make##type##Accessor (T1 a1)		\
+  {									\
+    return MakeAccessorHelper<type##Value> (a1);		\
+  }									\
+  template <typename T1, typename T2>					\
+  Ptr<const AttributeAccessor> Make##type##Accessor (T1 a1, T2 a2)	\
+  {									\
+    return MakeAccessorHelper<type##Value> (a1, a2);	\
+  }
+
+#define ATTRIBUTE_VALUE_DEFINE(type)					\
+  class type##Value : public AttributeValue				\
+  {									\
+  public:								\
+    type##Value (const type &value);					\
+    void Set (const type &value);					\
+    type Get (void) const;						\
+    virtual Attribute Copy (void) const;				\
+    virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const; \
+    virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker); \
+    type##Value (Attribute value);					\
+    operator Attribute () const;					\
+  private:								\
+    type m_value;							\
+  };
+
+#define ATTRIBUTE_CONVERTER_DEFINE(type)	\
+  type (Attribute value);			\
+  operator Attribute () const;
+
+#define ATTRIBUTE_CHECKER_DEFINE(type)				\
+  class type##Checker : public AttributeChecker {};		\
+  Ptr<const AttributeChecker> Make##type##Checker (void);	\
+
+#define ATTRIBUTE_VALUE_IMPLEMENT(type)					\
+  type##Value::type##Value (const type &value)				\
+  : m_value (value) {}							\
+  void type##Value::Set (const type &v) {				\
+    m_value = v;							\
+  }									\
+  type type##Value::Get (void) const {					\
+    return m_value;							\
+  }									\
+  Attribute								\
+  type##Value::Copy (void) const {					\
+    return Attribute::Create<type##Value> (*this);			\
+  }									\
+  std::string								\
+  type##Value::SerializeToString (Ptr<const AttributeChecker> checker) const { \
+    std::ostringstream oss;						\
+    oss << m_value;							\
+    return oss.str ();							\
+  }									\
+  bool									\
+  type##Value::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker) { \
+    std::istringstream iss;						\
+    iss.str (value);							\
+    iss >> m_value;							\
+    return !iss.bad () && !iss.fail ();					\
+  }									\
+  type##Value::type##Value (Attribute value)				\
+  {									\
+    type##Value *v = value.DynCast<type##Value *> ();			\
+    if (v == 0)								\
+      {									\
+	NS_FATAL_ERROR ("Unexpected type of value. Expected \"" << #type << "Value\""); \
+      }									\
+    m_value = v->Get ();						\
+  }									\
+  type##Value::operator Attribute () const				\
+  {									\
+    return Attribute::Create<type##Value> (*this);			\
+  }
+
+#define ATTRIBUTE_CHECKER_IMPLEMENT(type)				\
+  Ptr<const AttributeChecker> Make##type##Checker (void)		\
+  {									\
+    return MakeSimpleAttributeChecker<type##Value,type##Checker> ();	\
+  }									\
+
+#define ATTRIBUTE_CONVERTER_IMPLEMENT(type)				\
+  type::type (Attribute value)						\
+  {									\
+    const type##Value *v = value.DynCast<const type##Value *> ();	\
+    if (v == 0)								\
+      {									\
+      NS_FATAL_ERROR ("Unexpected type of value. Expected \"" << #type << "Value\""); \
+      }									\
+    *this = v->Get ();							\
+  }									\
+  type::operator Attribute () const					\
+  {									\
+    return Attribute::Create<type##Value> (*this);			\
+  }
+
+
+#define VALUE_HELPER_HEADER_1(type) \
+  ATTRIBUTE_CONVERTER_DEFINE (type)
+
+#define VALUE_HELPER_HEADER_2(type)					\
+  ATTRIBUTE_VALUE_DEFINE (type);					\
+  ATTRIBUTE_ACCESSOR_DEFINE (type);					\
+  ATTRIBUTE_CHECKER_DEFINE (type);
+
+#define VALUE_HELPER_CPP(type)						\
+  ATTRIBUTE_CHECKER_IMPLEMENT (type);					\
+  ATTRIBUTE_CONVERTER_IMPLEMENT (type);					\
+  ATTRIBUTE_VALUE_IMPLEMENT (type);
+
+
+
+#endif /* VALUE_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/attribute-test.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,475 @@
+#ifdef RUN_SELF_TESTS
+#include "test.h"
+#include "object.h"
+#include "boolean.h"
+#include "integer.h"
+#include "uinteger.h"
+#include "enum.h"
+#include "string.h"
+#include "random-variable.h"
+#include "double.h"
+#include "object-vector.h"
+#include "traced-value.h"
+#include "trace-source-accessor.h"
+
+namespace ns3 {
+
+class ValueClassTest 
+{
+public:
+  ValueClassTest () {}
+  VALUE_HELPER_HEADER_1 (ValueClassTest);
+private:
+  int m_v;
+};
+bool operator != (const ValueClassTest &a, const ValueClassTest &b)
+{
+  return true;
+}
+std::ostream & operator << (std::ostream &os, ValueClassTest v)
+{
+  return os;
+}
+std::istream & operator >> (std::istream &is, ValueClassTest &v)
+{
+  return is;
+}
+VALUE_HELPER_HEADER_2 (ValueClassTest);
+VALUE_HELPER_CPP (ValueClassTest);
+
+class AttributeTest : public Test
+{
+public:
+  AttributeTest ();
+  virtual bool RunTests (void);
+private:
+  void NotifySource1 (int8_t old, int8_t n) {
+    m_got1 = n;
+  }
+  void NotifySource2 (double a, int b, float c) {
+    m_got2 = a;
+  }
+  void NotifySourceValue (ValueClassTest old, ValueClassTest n) {
+    m_gotValue = n;
+  }
+  int64_t m_got1;
+  double m_got2;
+  ValueClassTest m_gotValue;
+};
+
+class Derived : public Object
+{
+public:
+  static TypeId GetTypeId (void) {
+    static TypeId tid = TypeId ("Derived")
+      .SetParent<Object> ()
+      ;
+    return tid;
+  }
+};
+
+class AttributeObjectTest : public Object
+{
+public:
+  enum TestEnum {
+    TEST_A,
+    TEST_B,
+    TEST_C
+  };
+  static TypeId GetTypeId (void) {
+    static TypeId tid = TypeId ("AttributeObjectTest")
+      .SetParent<Object> ()
+      .AddAttribute ("TestBoolName", "help text",
+		     Boolean (false),
+		     MakeBooleanAccessor (&AttributeObjectTest::m_boolTest),
+		     MakeBooleanChecker ())
+      .AddAttribute ("TestBoolA", "help text",
+		     Boolean (false),
+		     MakeBooleanAccessor (&AttributeObjectTest::DoSetTestB,
+					   &AttributeObjectTest::DoGetTestB),
+		     MakeBooleanChecker ())
+      .AddAttribute ("TestPtr", "help text", 
+		     Ptr<Derived> (0),
+		     MakePtrAccessor (&AttributeObjectTest::m_derived),
+		     MakePtrChecker<Derived> ())
+      .AddAttribute ("TestInt16", "help text",
+		     Integer (-2),
+		     MakeIntegerAccessor (&AttributeObjectTest::m_int16),
+		     MakeIntegerChecker<int16_t> ())
+      .AddAttribute ("TestInt16WithBounds", "help text",
+		     Integer (-2),
+		     MakeIntegerAccessor (&AttributeObjectTest::m_int16WithBounds),
+		     MakeIntegerChecker (-5, 10))
+      .AddAttribute ("TestInt16SetGet", "help text",
+		     Integer (6),
+		     MakeIntegerAccessor (&AttributeObjectTest::DoSetInt16,
+				       &AttributeObjectTest::DoGetInt16),
+		     MakeIntegerChecker<int16_t> ())
+      .AddAttribute ("TestUint8", "help text",
+		     Uinteger (1),
+		     MakeUintegerAccessor (&AttributeObjectTest::m_uint8),
+		     MakeUintegerChecker<uint8_t> ())
+      .AddAttribute ("TestEnum", "help text",
+		     Enum (TEST_A),
+		     MakeEnumAccessor (&AttributeObjectTest::m_enum),
+		     MakeEnumChecker (TEST_A, "TestA",
+				      TEST_B, "TestB",
+				      TEST_C, "TestC"))
+      .AddAttribute ("TestRandom", "help text",
+		     ConstantVariable (1.0),
+		     MakeRandomVariableAccessor (&AttributeObjectTest::m_random),
+		     MakeRandomVariableChecker ())
+      .AddAttribute ("TestFloat", "help text",
+		     Double (-1.1),
+		     MakeDoubleAccessor (&AttributeObjectTest::m_float),
+		     MakeDoubleChecker<float> ())
+      .AddAttribute ("TestVector1", "help text",
+		     ObjectVector (),
+		     MakeObjectVectorAccessor (&AttributeObjectTest::m_vector1),
+		     MakeObjectVectorChecker ())
+      .AddAttribute ("TestVector2", "help text",
+		     ObjectVector (),
+		     MakeObjectVectorAccessor (&AttributeObjectTest::DoGetVectorN,
+						&AttributeObjectTest::DoGetVector),
+		     MakeObjectVectorChecker ())
+      .AddAttribute ("IntegerTraceSource1", "help text",
+		     Integer (-2),
+		     MakeIntegerAccessor (&AttributeObjectTest::m_intSrc1),
+		     MakeIntegerChecker<int8_t> ())
+      .AddAttribute ("IntegerTraceSource2", "help text",
+		     Integer (-2),
+		     MakeIntegerAccessor (&AttributeObjectTest::DoSetIntSrc,
+					  &AttributeObjectTest::DoGetIntSrc),
+		     MakeIntegerChecker<int8_t> ())
+      .AddAttribute ("ValueClassSource", "help text",
+		     ValueClassTest (),
+		     MakeValueClassTestAccessor (&AttributeObjectTest::m_valueSrc),
+		     MakeValueClassTestChecker ())
+      .AddTraceSource ("Source1", "help test",
+		       MakeTraceSourceAccessor (&AttributeObjectTest::m_intSrc1))
+      .AddTraceSource ("Source2", "help text",
+		       MakeTraceSourceAccessor (&AttributeObjectTest::m_cb))
+      .AddTraceSource ("ValueSource", "help text",
+		       MakeTraceSourceAccessor (&AttributeObjectTest::m_valueSrc))
+      ;
+        
+    return tid;
+  }
+
+  void AddToVector1 (void) {
+    m_vector1.push_back (CreateObject<Derived> ());
+  }
+  void AddToVector2 (void) {
+    m_vector2.push_back (CreateObject<Derived> ());
+  }
+
+  void InvokeCb (double a, int b, float c) {
+    m_cb (a,b,c);
+  }
+
+private:
+  void DoSetTestB (bool v) {
+    m_boolTestA = v;
+  }
+  bool DoGetTestB (void) const {
+    return m_boolTestA;
+  }
+  int16_t DoGetInt16 (void) const {
+    return m_int16SetGet;
+  }
+  void DoSetInt16 (int16_t v) {
+    m_int16SetGet = v;
+  }
+  uint32_t DoGetVectorN (void) const {
+    return m_vector2.size ();
+  }
+  Ptr<Derived> DoGetVector (uint32_t i) const {
+    return m_vector2[i];
+  }
+  void DoSetIntSrc (int8_t v) {
+    m_intSrc2 = v;
+  }
+  int8_t DoGetIntSrc (void) const {
+    return m_intSrc2;
+  }
+  bool m_boolTestA;
+  bool m_boolTest;
+  Ptr<Derived> m_derived;
+  int16_t m_int16;
+  int16_t m_int16WithBounds;
+  int16_t m_int16SetGet;
+  uint8_t m_uint8;
+  float m_float;
+  enum TestEnum m_enum;
+  RandomVariable m_random;
+  std::vector<Ptr<Derived> > m_vector1;
+  std::vector<Ptr<Derived> > m_vector2;
+  TracedValue<int8_t> m_intSrc1;
+  TracedValue<int8_t> m_intSrc2;
+  TracedCallback<double, int, float> m_cb;
+  TracedValue<ValueClassTest> m_valueSrc;
+};
+
+
+#define CHECK_GET_STR(p,name,value)		\
+  {						\
+    std::string expected = value;		\
+    std::string got;				\
+    bool ok = p->GetAttribute (name, got);	\
+    NS_TEST_ASSERT (ok);			\
+    NS_TEST_ASSERT_EQUAL (got, expected);	\
+  }
+#define CHECK_GET_PARAM(p,name,type,value)		\
+  {							\
+    const type expected = value;			\
+    type got = value;					\
+    Attribute v = p->GetAttribute (name);		\
+    got = v;						\
+    NS_TEST_ASSERT_EQUAL (got.Get (), expected.Get ());	\
+  }
+
+NS_OBJECT_ENSURE_REGISTERED (AttributeObjectTest);
+
+AttributeTest::AttributeTest ()
+  : Test ("Attribute")
+{}
+bool 
+AttributeTest::RunTests (void)
+{
+  bool result = true;
+
+  AttributeList params;
+  Ptr<AttributeObjectTest> p;
+  NS_TEST_ASSERT (params.Set ("AttributeObjectTest::TestBoolName", String ("false")));
+  p = CreateObject<AttributeObjectTest> (params);
+  CHECK_GET_STR (p, "TestBoolName", "false");
+  CHECK_GET_PARAM (p, "TestBoolName", Boolean, false);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestBoolName", String ("true")));
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", Boolean, true);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestBoolName", Boolean (false)));
+  CHECK_GET_STR (p, "TestBoolName", "false");
+  CHECK_GET_PARAM (p, "TestBoolName", Boolean, false);
+
+  p = CreateObjectWith<AttributeObjectTest> ("TestBoolName", String ("true"));
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", Boolean, true);
+
+  p = CreateObjectWith<AttributeObjectTest> ("TestBoolName", Boolean (true));
+  CHECK_GET_STR (p, "TestBoolName", "true");
+  CHECK_GET_PARAM (p, "TestBoolName", Boolean, true);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestBoolA", String ("false")));
+  CHECK_GET_STR (p, "TestBoolA", "false");
+  CHECK_GET_PARAM (p, "TestBoolA", Boolean, false);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestBoolA", String ("true")));
+  CHECK_GET_STR (p, "TestBoolA", "true");
+  CHECK_GET_PARAM (p, "TestBoolA", Boolean, true);
+
+
+  Ptr<Derived> derived = p->GetAttribute ("TestPtr");
+  NS_TEST_ASSERT (derived == 0);
+  derived = Create<Derived> ();
+  NS_TEST_ASSERT (p->SetAttribute("TestPtr", derived));
+  Ptr<Derived> stored = p->GetAttribute ("TestPtr");
+  NS_TEST_ASSERT (stored == derived);
+  Ptr<Object> storedBase = p->GetAttribute ("TestPtr");
+  NS_TEST_ASSERT (stored == storedBase);
+  Ptr<AttributeObjectTest> x = p->GetAttribute ("TestPtr");
+  NS_TEST_ASSERT (x == 0);
+
+  p = CreateObjectWith<AttributeObjectTest> ("TestPtr", Create<Derived> ());
+  NS_TEST_ASSERT (p != 0);
+  derived = 0;
+  derived = p->GetAttribute ("TestPtr");
+  NS_TEST_ASSERT (derived != 0);
+
+  CHECK_GET_STR (p, "TestInt16", "-2");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, -2);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16", String ("-5")));
+  CHECK_GET_STR (p, "TestInt16", "-5");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, -5);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16", Integer (+2)));
+  CHECK_GET_STR (p, "TestInt16", "2");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, +2);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16", Integer (-32768)));
+  CHECK_GET_STR (p, "TestInt16", "-32768");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, -32768);
+
+  NS_TEST_ASSERT (!p->SetAttribute("TestInt16", Integer (-32769)));
+  CHECK_GET_STR (p, "TestInt16", "-32768");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, -32768);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16", Integer (32767)));
+  CHECK_GET_STR (p, "TestInt16", "32767");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, 32767);
+
+  NS_TEST_ASSERT (!p->SetAttribute("TestInt16", Integer (32768)));
+  CHECK_GET_STR (p, "TestInt16", "32767");
+  CHECK_GET_PARAM (p, "TestInt16", Integer, 32767);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16WithBounds", Integer (10)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "10");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", Integer, 10);
+  NS_TEST_ASSERT (!p->SetAttribute("TestInt16WithBounds", Integer (11)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "10");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", Integer, 10);
+
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16WithBounds", Integer (-5)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "-5");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", Integer, -5);
+  NS_TEST_ASSERT (!p->SetAttribute("TestInt16WithBounds", Integer (-6)));
+  CHECK_GET_STR (p, "TestInt16WithBounds", "-5");
+  CHECK_GET_PARAM (p, "TestInt16WithBounds", Integer, -5);
+
+  CHECK_GET_STR (p, "TestInt16SetGet", "6");
+  CHECK_GET_PARAM (p, "TestInt16SetGet", Integer, 6);
+  NS_TEST_ASSERT (p->SetAttribute("TestInt16SetGet", Integer (0)));
+  CHECK_GET_STR (p, "TestInt16SetGet", "0");
+  CHECK_GET_PARAM (p, "TestInt16SetGet", Integer, 0);
+
+  CHECK_GET_STR (p, "TestUint8", "1");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 1);
+  NS_TEST_ASSERT (p->SetAttribute("TestUint8", Uinteger (0)));
+  CHECK_GET_STR (p, "TestUint8", "0");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 0);
+  NS_TEST_ASSERT (p->SetAttribute("TestUint8", Uinteger (255)));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 255);
+  NS_TEST_ASSERT (p->SetAttribute("TestUint8", String ("255")));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 255);
+  NS_TEST_ASSERT (!p->SetAttribute("TestUint8", String ("256")));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 255);
+  NS_TEST_ASSERT (!p->SetAttribute("TestUint8", String ("-1")));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 255);
+  NS_TEST_ASSERT (!p->SetAttribute("TestUint8", Uinteger ((uint64_t)-1)));
+  CHECK_GET_STR (p, "TestUint8", "255");
+  CHECK_GET_PARAM (p, "TestUint8", Uinteger, 255);
+
+  CHECK_GET_STR (p, "TestFloat", "-1.1");
+  NS_TEST_ASSERT (p->SetAttribute("TestFloat", Double ((float)+2.3)));
+  CHECK_GET_PARAM (p, "TestFloat", Double, (float)+2.3);
+
+  CHECK_GET_STR (p, "TestEnum", "TestA");
+  CHECK_GET_PARAM (p, "TestEnum", Enum, AttributeObjectTest::TEST_A);
+  NS_TEST_ASSERT (p->SetAttribute("TestEnum", Enum (AttributeObjectTest::TEST_C)));
+  CHECK_GET_STR (p, "TestEnum", "TestC");
+  CHECK_GET_PARAM (p, "TestEnum", Enum, AttributeObjectTest::TEST_C);
+  NS_TEST_ASSERT (p->SetAttribute("TestEnum", String ("TestB")));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", Enum, AttributeObjectTest::TEST_B);
+  NS_TEST_ASSERT (!p->SetAttribute("TestEnum", String ("TestD")));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", Enum, AttributeObjectTest::TEST_B);
+  NS_TEST_ASSERT (!p->SetAttribute("TestEnum", Enum (5)));
+  CHECK_GET_STR (p, "TestEnum", "TestB");
+  CHECK_GET_PARAM (p, "TestEnum", Enum, AttributeObjectTest::TEST_B);
+
+  RandomVariable ran = p->GetAttribute ("TestRandom");
+  NS_TEST_ASSERT (p->SetAttribute("TestRandom", UniformVariable (0.0, 1.0)));
+  NS_TEST_ASSERT (p->SetAttribute("TestRandom", ConstantVariable (10.0)));
+
+  {
+    ObjectVector vector = p->GetAttribute ("TestVector1");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 0);
+    p->AddToVector1 ();
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 0);
+    vector = p->GetAttribute ("TestVector1");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 1);
+    Ptr<Object> a = vector.Get (0);
+    NS_TEST_ASSERT_UNEQUAL (a, 0);
+    p->AddToVector1 ();
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 1);
+    vector = p->GetAttribute ("TestVector1");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 2);
+  }
+
+  {
+    ObjectVector vector = p->GetAttribute ("TestVector2");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 0);
+    p->AddToVector2 ();
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 0);
+    vector = p->GetAttribute ("TestVector2");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 1);
+    Ptr<Object> a = vector.Get (0);
+    NS_TEST_ASSERT_UNEQUAL (a, 0);
+    p->AddToVector2 ();
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 1);
+    vector = p->GetAttribute ("TestVector2");
+    NS_TEST_ASSERT_EQUAL (vector.GetN (), 2);
+  }
+
+  NS_TEST_ASSERT (AttributeList::GetGlobal ()->Set ("AttributeObjectTest::TestBoolName", String ("true")));
+  p = CreateObjectWith<AttributeObjectTest> ();
+  Boolean boolV = p->GetAttribute ("TestBoolName");
+  NS_TEST_ASSERT_EQUAL (boolV, Boolean (true));
+
+  NS_TEST_ASSERT (AttributeList::GetGlobal ()->Set ("AttributeObjectTest::TestBoolName", String ("false")));
+  p = CreateObjectWith<AttributeObjectTest> ();
+  boolV = p->GetAttribute ("TestBoolName");
+  NS_TEST_ASSERT_EQUAL (boolV, Boolean (false));
+
+  Integer i = p->GetAttribute ("IntegerTraceSource1");
+  NS_TEST_ASSERT_EQUAL (i.Get (), -2);
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (+5)));
+  i = p->GetAttribute ("IntegerTraceSource1");
+  NS_TEST_ASSERT_EQUAL (i.Get (), +5);
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (127)));
+  NS_TEST_ASSERT (!p->SetAttribute ("IntegerTraceSource1", Integer (128)));
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (-128)));
+  NS_TEST_ASSERT (!p->SetAttribute ("IntegerTraceSource1", Integer (-129)));
+
+  i = p->GetAttribute ("IntegerTraceSource2");
+  NS_TEST_ASSERT_EQUAL (i.Get (), -2);
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource2", Integer (+5)));
+  i = p->GetAttribute ("IntegerTraceSource2");
+  NS_TEST_ASSERT_EQUAL (i.Get (), +5);
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource2", Integer (127)));
+  NS_TEST_ASSERT (!p->SetAttribute ("IntegerTraceSource2", Integer (128)));
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource2", Integer (-128)));
+  NS_TEST_ASSERT (!p->SetAttribute ("IntegerTraceSource2", Integer (-129)));
+
+  m_got1 = -2;
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (-1)));
+  NS_TEST_ASSERT (p->TraceSourceConnect ("Source1", MakeCallback (&AttributeTest::NotifySource1, this)));
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (0)));
+  NS_TEST_ASSERT_EQUAL (m_got1, 0);
+  NS_TEST_ASSERT (p->TraceSourceDisconnect ("Source1", MakeCallback (&AttributeTest::NotifySource1, this)));
+  NS_TEST_ASSERT (p->SetAttribute ("IntegerTraceSource1", Integer (1)));
+  NS_TEST_ASSERT_EQUAL (m_got1, 0);
+
+  m_got2 = 4.3;
+  p->InvokeCb (1.0, -5, 0.0);
+  NS_TEST_ASSERT_EQUAL (m_got2, 4.3);
+  NS_TEST_ASSERT (p->TraceSourceConnect ("Source2", MakeCallback (&AttributeTest::NotifySource2, this)));
+  NS_TEST_ASSERT_EQUAL (m_got2, 4.3);
+  p->InvokeCb (1.0, -5, 0.0);
+  NS_TEST_ASSERT_EQUAL (m_got2, 1.0);
+  NS_TEST_ASSERT (p->TraceSourceDisconnect ("Source2", MakeCallback (&AttributeTest::NotifySource2, this)));
+  p->InvokeCb (-1.0, -5, 0.0);
+  NS_TEST_ASSERT_EQUAL (m_got2, 1.0);
+
+  NS_TEST_ASSERT (p->TraceSourceConnect ("ValueSource", MakeCallback (&AttributeTest::NotifySourceValue, this)));
+  
+
+
+  return result;
+}
+
+
+
+static AttributeTest g_parameterTest;
+
+} // namespace ns3
+
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/attribute.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,171 @@
+#include "attribute.h"
+#include "log.h"
+#include "fatal-error.h"
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("AttributeValue");
+
+namespace ns3 {
+
+AttributeValue::AttributeValue ()
+  : m_count (1)
+{}
+AttributeValue::AttributeValue (const AttributeValue &o)
+  : m_count (1)
+{}
+AttributeValue &
+AttributeValue::operator = (const AttributeValue &o)
+{
+  return *this;
+}
+AttributeValue::~AttributeValue ()
+{}
+
+/***************************************************************
+ *   Big interesting warning.
+ *   ------------------------
+ *
+ * One might wonder why we re-implement a smart pointer below 
+ * in the Attribute class. This is a very good question and the answer
+ * is unfortunately pretty complicated.
+ *
+ * 1) We could have requested the user to use Ptr<AttributeValue> and save us
+ *    a lot of pain. This, however, does not work because our smart 
+ *    pointer needs a special constructor which can be used to convert
+ *    objects of type Ptr<T> into a PtrValue<T> to hold the pointer.
+ *
+ * 2) We could have made the m_value member variable below a Ptr<AttributeValue>
+ *    rather than store a raw pointer. This, however, does not work
+ *    because this would mean that the constructor Attribute (AttributeValue *)
+ *    should be morphed into Attribute (Ptr<AttributeValue>) which, unfortunately,
+ *    would conflict with the template constructor Attribute (Ptr<T>)...
+ *
+ * This is definitely not fun.   
+ */
+Attribute::Attribute ()
+  : m_value (0)
+{}
+Attribute::Attribute (const Attribute &o)
+  : m_value (o.m_value)
+{
+  if (m_value != 0)
+    {
+      m_value->m_count++;
+      NS_LOG_DEBUG ("this="<<m_value<<" ++count="<<m_value->m_count);
+    }
+}
+Attribute &
+Attribute::operator = (const Attribute &o)
+{
+  if (&o != this)
+    {
+      if (m_value != 0)
+	{
+	  m_value->m_count--;
+	  NS_LOG_DEBUG ("this="<<m_value<<" --count="<<m_value->m_count);
+	  if (m_value->m_count == 0)
+	    {
+	      delete m_value;
+	      m_value = 0;
+	    }
+	}
+      m_value = o.m_value;
+      if (m_value != 0)
+	{
+	  m_value->m_count++;
+	  NS_LOG_DEBUG ("this="<<m_value<<" ++count="<<m_value->m_count);
+	}
+    }
+  return *this;
+}
+Attribute::~Attribute ()
+{
+  if (m_value != 0) 
+    {
+      m_value->m_count--;
+      NS_LOG_DEBUG ("this="<<m_value<<" --count="<<m_value->m_count);
+      if (m_value->m_count == 0)
+	{
+	  delete m_value;
+	  m_value = 0;
+	}
+    }
+}
+Attribute::Attribute (AttributeValue *value)
+  : m_value (value)
+{
+  NS_LOG_DEBUG ("this="<<m_value<<" count="<<((m_value!=0)?m_value->m_count:666));
+}
+
+Attribute 
+Attribute::Copy (void) const
+{
+  return m_value->Copy ();
+}
+std::string 
+Attribute::SerializeToString (Ptr<const AttributeChecker> checker) const
+{
+  return m_value->SerializeToString (checker);
+}
+bool 
+Attribute::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
+{
+  return m_value->DeserializeFromString (value, checker);
+}
+
+AttributeAccessor::AttributeAccessor ()
+  : m_count (1)
+{}
+void 
+AttributeAccessor::Ref (void) const
+{
+  m_count++;
+}
+void 
+AttributeAccessor::Unref (void) const
+{
+  m_count--;
+  if (m_count == 0)
+    {
+      delete this;
+    }
+}
+AttributeAccessor::~AttributeAccessor ()
+{}
+
+AttributeChecker::AttributeChecker ()
+  : m_count (1)
+{}
+void 
+AttributeChecker::Ref (void) const
+{
+  m_count++;
+}
+void 
+AttributeChecker::Unref (void) const
+{
+  m_count--;
+  if (m_count == 0)
+    {
+      delete this;
+    }
+}
+AttributeChecker::~AttributeChecker ()
+{}
+
+std::string 
+PtrValueBase::SerializeToString (Ptr<const AttributeChecker> checker) const
+{
+  std::ostringstream oss;
+  oss << PeekObjectBase ();
+  return oss.str ();
+}
+
+bool 
+PtrValueBase::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
+{
+  // XXX
+  return false;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/attribute.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,377 @@
+#ifndef ATTRIBUTE_H
+#define ATTRIBUTE_H
+
+#include <string>
+#include <stdint.h>
+#include "ptr.h"
+#include "object-base.h"
+
+namespace ns3 {
+
+class AttributeAccessor;
+class AttributeChecker;
+class Attribute;
+
+class AttributeValue
+{
+public:
+  AttributeValue ();
+  AttributeValue (const AttributeValue &o);
+  AttributeValue &operator = (const AttributeValue &o);
+  virtual ~AttributeValue ();
+
+  virtual Attribute Copy (void) const = 0;
+  virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const = 0;
+  virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker) = 0;
+private:
+  friend class Attribute;
+  uint32_t m_count;
+};
+
+class Attribute
+{
+public:
+  Attribute ();
+  Attribute (const Attribute &o);
+  Attribute &operator = (const Attribute &o);
+  ~Attribute ();
+
+  Attribute Copy (void) const;
+  std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
+  bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
+
+  template <typename T>
+  static Attribute Create (void);
+  template <typename T, typename T1>
+  static Attribute Create (T1 a1);
+
+  template <typename T>
+  T DynCast (void) const;
+
+  template <typename T>
+  Attribute (Ptr<T> pointer);
+  template <typename T>
+  operator Ptr<T> ();
+
+private:
+  Attribute (AttributeValue *value);
+  AttributeValue *m_value;
+};
+
+class AttributeAccessor : public ObjectBase
+{
+public:
+  AttributeAccessor ();
+  void Ref (void) const;
+  void Unref (void) const;
+  virtual ~AttributeAccessor ();
+
+  /**
+   * \param object the object instance to set the value in
+   * \param value the value to set
+   * \returns true if the value is valid and it could be set
+   *          successfully, false otherwise.
+   */
+  virtual bool Set (ObjectBase * object, Attribute value) const = 0;
+  virtual bool Get (const ObjectBase * object, Attribute value) const = 0;
+private:
+  mutable uint32_t m_count;
+};
+
+class AttributeChecker : public ObjectBase
+{
+public:
+  AttributeChecker ();
+  void Ref (void) const;
+  void Unref (void) const;
+  virtual ~AttributeChecker ();
+  virtual bool Check (Attribute value) const = 0;
+private:
+  mutable uint32_t m_count;
+};
+
+template <typename T, typename BASE>
+Ptr<AttributeChecker>
+MakeSimpleAttributeChecker (void);
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (Ptr<U> T::*memberVariable);
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (void (T::*setter) (Ptr<U>));
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (Ptr<U> (T::*getter) (void) const);
+
+
+class PtrChecker : public AttributeChecker {};
+
+template <typename T>
+Ptr<AttributeChecker> MakePtrChecker (void);
+
+
+
+} // namespace ns3
+
+namespace ns3 {
+
+/********************************************************
+ *   The class used to access the pointer stored in a
+ *   PtrValue<T> AttributeValue instance.
+ ********************************************************/
+
+class PtrValueBase : public AttributeValue
+{
+public:
+  virtual ObjectBase *PeekObjectBase (void) const = 0;
+  virtual bool SetObjectBase (ObjectBase *object) = 0;
+  virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
+  virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
+};
+
+} // namespace ns3
+
+/********************************************************
+ *        Store the content of a Ptr<T> in a AttributeValue
+ ********************************************************/
+
+namespace {
+
+template <typename T>
+class PtrValue : public ns3::PtrValueBase
+{
+public:
+  PtrValue (ns3::Ptr<T> pointer) 
+    : m_pointer (pointer) {}
+
+  virtual ns3::ObjectBase *PeekObjectBase (void) const {
+    return PeekPointer (m_pointer);
+  }
+  virtual bool SetObjectBase (ns3::ObjectBase *object) {
+    T *ptr = dynamic_cast<T *> (object);
+    if (ptr == 0)
+      {
+	return false;
+      }
+    m_pointer = ptr;
+    return true;
+  }
+  virtual ns3::Attribute Copy (void) const {
+    return ns3::Attribute::Create<PtrValue<T> > (*this);
+  }
+private:
+  ns3::Ptr<T> m_pointer;
+};
+
+template <typename T>
+class APtrChecker : public ns3::PtrChecker
+{
+  virtual bool Check (ns3::Attribute val) const {
+    const ns3::PtrValueBase *value = val.DynCast<const ns3::PtrValueBase *> ();
+    if (value == 0)
+      {
+	return false;
+      }
+    if (value->PeekObjectBase () == 0)
+      {
+	return true;
+      }
+    T *ptr = dynamic_cast<T*> (value->PeekObjectBase ());
+    if (ptr == 0)
+      {
+	return false;
+      }
+    return true;
+  }
+};
+
+/********************************************************
+ *              The Accessor associated to 
+ *               PtrValue<T>
+ ********************************************************/
+
+template <typename T, typename U>
+class PtrAccessor : public ns3::AttributeAccessor
+{
+public:
+  virtual ~PtrAccessor () {}
+  virtual bool Set (ns3::ObjectBase * object, ns3::Attribute val) const {
+      T *obj = dynamic_cast<T *> (object);
+      if (obj == 0)
+        {
+          return false;
+        }
+      const ns3::PtrValueBase *value = val.DynCast<const ns3::PtrValueBase *> ();
+      if (value == 0)
+        {
+          return false;
+        }
+      ns3::Ptr<U> ptr = dynamic_cast<U*> (value->PeekObjectBase ());
+      if (ptr == 0)
+        {
+          return false;
+        }
+      DoSet (obj, ptr);
+      return true;
+    }
+  virtual bool Get (const ns3::ObjectBase * object, ns3::Attribute val) const {
+      const T *obj = dynamic_cast<const T *> (object);
+      if (obj == 0)
+        {
+          return false;
+        }
+      ns3::PtrValueBase *value = val.DynCast<ns3::PtrValueBase *> ();
+      if (value == 0)
+        {
+          return false;
+        }
+      return value->SetObjectBase (PeekPointer (DoGet (obj)));
+    }
+private:
+  virtual void DoSet (T *object, ns3::Ptr<U> value) const = 0;
+  virtual ns3::Ptr<U> DoGet (const T *object) const = 0;
+};
+
+} // anonymous namespace
+
+/********************************************************
+ *        The implementation of the Attribute 
+ *          class template methods.
+ ********************************************************/
+
+namespace ns3 {
+
+template <typename T>
+Attribute 
+Attribute::Create (void)
+{
+  return Attribute (new T ());
+}
+template <typename T, typename T1>
+Attribute 
+Attribute::Create (T1 a1)
+{
+  return Attribute (new T (a1));
+}
+
+template <typename T>
+T
+Attribute::DynCast (void) const
+{
+  return dynamic_cast<T> (m_value);
+}
+
+template <typename T>
+Attribute::Attribute (Ptr<T> pointer)
+  : m_value (new PtrValue<T> (pointer))
+{}
+template <typename T>
+Attribute::operator Ptr<T> ()
+{
+  PtrValueBase *value = DynCast<PtrValueBase *> ();
+  if (value == 0)
+    {
+      return 0;
+    }
+  ObjectBase *objectBase = value->PeekObjectBase ();
+  T *obj = dynamic_cast<T *> (objectBase);
+  if (obj == 0)
+    {
+      return 0;
+    }
+  return obj;
+}
+
+
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (Ptr<U> T::*memberVariable)
+{
+  struct MemberVariable : public PtrAccessor<T,U>
+  {
+    Ptr<U> T::*m_memberVariable;
+    virtual MemberVariable *Copy (void) const {
+      return new MemberVariable (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      (object->*m_memberVariable) = value;
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return object->*m_memberVariable;
+    }
+  } *spec = new MemberVariable ();
+  spec->m_memberVariable = memberVariable;
+  return Ptr<const AttributeAccessor> (spec, false);
+}
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (void (T::*setter) (Ptr<U>))
+{
+  struct MemberMethod : public PtrAccessor<T,U>
+  {
+    void (T::*m_setter) (Ptr<U>);
+    virtual MemberMethod *Copy (void) const {
+      return new MemberMethod (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      (object->*m_setter) (value);
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return 0;
+      //return (object->*m_getter) ();
+    }
+  } *spec = new MemberMethod ();
+  spec->m_setter = setter;
+  return Ptr<const AttributeAccessor> (spec, false);
+}
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakePtrAccessor (Ptr<U> (T::*getter) (void) const)
+{
+  struct MemberMethod : public PtrAccessor<T,U>
+  {
+    void (T::*m_getter) (Ptr<U>);
+    virtual MemberMethod *Copy (void) const {
+      return new MemberMethod (*this);
+    }
+    virtual void DoSet (T *object, Ptr<U> value) const {
+      //(object->*m_setter) (value);
+    }
+    virtual Ptr<U> DoGet (const T *object) const {
+      return (object->*m_getter) ();
+    }
+  } *spec = new MemberMethod ();
+  spec->m_getter = getter;
+  return Ptr<const AttributeAccessor> (spec, false);
+}
+
+
+template <typename T>
+Ptr<AttributeChecker>
+MakePtrChecker (void)
+{
+  return Create<APtrChecker<T> > ();
+}
+
+template <typename T, typename BASE>
+Ptr<AttributeChecker>
+MakeSimpleAttributeChecker (void)
+{
+  struct SimpleAttributeChecker : public BASE
+  {
+    virtual bool Check (Attribute value) const {
+      return value.DynCast<const T *> () != 0;
+    }
+  } *checker = new SimpleAttributeChecker ();
+  return Ptr<AttributeChecker> (checker, false);
+}
+
+
+} // namespace ns3
+
+#endif /* ATTRIBUTE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/boolean.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,66 @@
+#include "boolean.h"
+#include "fatal-error.h"
+
+namespace ns3 {
+
+Boolean::Boolean ()
+  : m_value (false)
+{}
+Boolean::Boolean (bool value)
+  : m_value (value)
+{}
+void 
+Boolean::Set (bool value)
+{
+  m_value = value;
+}
+bool 
+Boolean::Get (void) const
+{
+  return m_value;
+}
+Boolean::operator bool () const
+{
+  return m_value;
+}
+
+std::ostream & operator << (std::ostream &os, const Boolean &value)
+{
+  if (value.Get ())
+    {
+      os << "true";
+    }
+  else
+    {
+      os << "false";
+    }
+  return os;
+}
+std::istream & operator >> (std::istream &is, Boolean &value)
+{
+  std::string v;
+  is >> v;
+  if (v == "true" ||
+      v == "1" ||
+      v == "t")
+    {
+      value.Set (true);
+    }
+  else if (v == "false" ||
+	   v == "0" ||
+	   v == "f")
+    {
+      value.Set (false);
+    }
+  else
+    {
+      is.setstate (std::ios_base::badbit);
+    }  
+  return is;
+}
+
+ATTRIBUTE_CONVERTER_IMPLEMENT (Boolean);
+ATTRIBUTE_VALUE_IMPLEMENT (Boolean);
+ATTRIBUTE_CHECKER_IMPLEMENT (Boolean);
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/boolean.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,33 @@
+#ifndef BOOLEAN_H
+#define BOOLEAN_H
+
+#include "attribute.h"
+#include "attribute-helper.h"
+
+namespace ns3 {
+
+class Boolean
+{
+public:
+  Boolean ();
+  Boolean (bool value);
+  void Set (bool value);
+  bool Get (void) const;
+
+  operator bool () const;
+
+  ATTRIBUTE_CONVERTER_DEFINE (Boolean);
+private:
+  bool m_value;
+};
+
+std::ostream & operator << (std::ostream &os, const Boolean &value);
+std::istream & operator >> (std::istream &is, Boolean &value);
+
+ATTRIBUTE_VALUE_DEFINE (Boolean);
+ATTRIBUTE_CHECKER_DEFINE (Boolean);
+ATTRIBUTE_ACCESSOR_DEFINE (Boolean);
+
+} // namespace ns3
+
+#endif /* BOOLEAN_H */
--- a/src/core/callback.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/callback.h	Wed Feb 27 22:19:39 2008 +0100
@@ -26,6 +26,7 @@
 #include "fatal-error.h"
 #include "empty.h"
 #include "type-traits.h"
+#include "object-base.h"
 
 namespace ns3 {
 
@@ -70,7 +71,8 @@
   }
 };
 
-class CallbackImplBase {
+class CallbackImplBase : public ObjectBase 
+{
 public:
   CallbackImplBase ()
     : m_count (1) {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/config.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,613 @@
+#include "config.h"
+#include "singleton.h"
+#include "object.h"
+#include "global-value.h"
+#include "object-vector.h"
+#include "log.h"
+#include <sstream>
+
+NS_LOG_COMPONENT_DEFINE ("Config");
+
+namespace ns3 {
+
+class ArrayMatcher
+{
+public:
+  ArrayMatcher (std::string element);
+  bool Matches (uint32_t i) const;
+private:
+  bool StringToUint32 (std::string str, uint32_t *value) const;
+  std::string m_element;
+};
+
+
+ArrayMatcher::ArrayMatcher (std::string element)
+  : m_element (element)
+{}
+bool 
+ArrayMatcher::Matches (uint32_t i) const
+{
+  if (m_element == "*")
+    {
+      NS_LOG_DEBUG ("Array "<<i<<" matches *");
+      return true;
+    }
+  std::string::size_type tmp;
+  tmp = m_element.find ("|");
+  if (tmp != std::string::npos)
+    {
+      std::string left = m_element.substr (0, tmp-0);
+      std::string right = m_element.substr (tmp+1, m_element.size () - (tmp + 1));
+      ArrayMatcher matcher = ArrayMatcher (left);
+      if (matcher.Matches (i))
+	{
+	  NS_LOG_DEBUG ("Array "<<i<<" matches "<<left);
+	  return true;
+	}
+      matcher = ArrayMatcher (right);
+      if (matcher.Matches (i))
+	{
+	  NS_LOG_DEBUG ("Array "<<i<<" matches "<<right);
+	  return true;
+	}
+      NS_LOG_DEBUG ("Array "<<i<<" does not match "<<m_element);
+      return false;
+    }
+  std::string::size_type leftBracket = m_element.find ("[");
+  std::string::size_type rightBracket = m_element.find ("]");
+  std::string::size_type dash = m_element.find ("-");
+  if (leftBracket == 0 && rightBracket == m_element.size () - 1 &&
+      dash > leftBracket && dash < rightBracket)
+    {
+      std::string lowerBound = m_element.substr (leftBracket + 1, dash - (leftBracket + 1));
+      std::string upperBound = m_element.substr (dash + 1, rightBracket - (dash + 1));
+      uint32_t min;
+      uint32_t max;
+      if (StringToUint32 (lowerBound, &min) && 
+	  StringToUint32 (upperBound, &max) &&
+	  i >= min && i <= max)
+        {
+	  NS_LOG_DEBUG ("Array "<<i<<" matches "<<m_element);
+          return true;
+        }
+      else
+	{
+	  NS_LOG_DEBUG ("Array "<<i<<" does not "<<m_element);
+	  return false;
+	}
+    }
+  uint32_t value;
+  if (StringToUint32 (m_element, &value) &&
+      i == value)
+    {
+      NS_LOG_DEBUG ("Array "<<i<<" matches "<<m_element);
+      return true;
+    }
+  NS_LOG_DEBUG ("Array "<<i<<" does not match "<<m_element);
+  return false;
+}
+
+bool
+ArrayMatcher::StringToUint32 (std::string str, uint32_t *value) const
+{
+  std::istringstream iss;
+  iss.str (str);
+  iss >> (*value);
+  return !iss.bad () && !iss.fail ();
+}
+
+
+class Resolver
+{
+public:
+  Resolver (std::string path);
+  virtual ~Resolver ();
+
+  void Resolve (Ptr<Object> root);
+private:
+  void DoResolve (std::string path, Ptr<Object> root);
+  void DoArrayResolve (std::string path, const ObjectVector &vector);
+  void DoResolveOne (Ptr<Object> object, std::string name);
+  std::string GetResolvedPath (std::string name) const;
+  virtual void DoOne (Ptr<Object> object, std::string name) = 0;
+  std::vector<std::string> m_workStack;
+  std::string m_path;
+};
+
+Resolver::Resolver (std::string path)
+  : m_path (path)
+{}
+Resolver::~Resolver ()
+{}
+
+void 
+Resolver::Resolve (Ptr<Object> root)
+{
+  DoResolve (m_path, root);
+}
+
+std::string
+Resolver::GetResolvedPath (std::string name) const
+{
+  std::string fullPath = "";
+  for (std::vector<std::string>::const_iterator i = m_workStack.begin (); i != m_workStack.end (); i++)
+    {
+      fullPath += "/" + *i;
+    }
+  fullPath += "/" + name;
+  return fullPath;
+}
+
+void 
+Resolver::DoResolveOne (Ptr<Object> object, std::string name)
+{
+  NS_LOG_DEBUG ("resolved="<<GetResolvedPath (name));
+  DoOne (object, name);
+}
+
+void
+Resolver::DoResolve (std::string path, Ptr<Object> root)
+{
+  NS_ASSERT (path != "");
+  std::string::size_type pos = path.find ("/");
+  if (pos != 0)
+    {
+      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
+      return;
+    }
+  std::string::size_type next = path.find ("/", 1);
+  if (next == std::string::npos)
+    {
+      std::string attributeName = path.substr (1, path.size ()-1);
+      NS_LOG_DEBUG ("handle attr="<<attributeName);
+      DoOne (root, attributeName);
+      return;
+    }
+  std::string item = path.substr (1, next-1);
+  std::string pathLeft = path.substr (next, path.size ()-next);
+
+  std::string::size_type dollarPos = item.find ("$");
+  if (dollarPos == 0)
+    {
+      // This is a call to GetObject
+      std::string tidString = item.substr (1, item.size () - 1);
+      NS_LOG_DEBUG ("GetObject="<<tidString<<"on path="<<GetResolvedPath (""));
+      TypeId tid = TypeId::LookupByName (tidString);
+      Ptr<Object> object = root->GetObject<Object> (tid);
+      if (object == 0)
+	{
+	  NS_LOG_DEBUG ("GetObject ("<<tidString<<") failed on path="<<GetResolvedPath (""));
+	  return;
+	}
+      m_workStack.push_back (item);
+      DoResolve (pathLeft, object);
+      m_workStack.pop_back ();
+    }
+  else 
+    {
+      // this is a normal attribute.
+      TypeId tid = root->GetRealTypeId ();
+      struct TypeId::AttributeInfo info;
+      if (!tid.LookupAttributeByName (item, &info))
+	{
+	  NS_LOG_DEBUG ("Requested item="<<item<<" does not exist on path="<<GetResolvedPath (""));
+	  return;
+	}
+      // attempt to cast to a pointer checker.
+      const PtrChecker *ptr = dynamic_cast<const PtrChecker *> (PeekPointer (info.checker));
+      if (ptr != 0)
+	{
+	  NS_LOG_DEBUG ("GetAttribute(ptr)="<<item<<" on path="<<GetResolvedPath (""));
+	  // XXX: This is not completely right because anything could be stored in a
+	  // Ptr<>. We really need to fix this by thinking seriously about our
+	  // object hierarchy.
+	  Ptr<Object> object = root->GetAttribute (item);
+	  if (object == 0)
+	    {
+	      NS_LOG_ERROR ("Requested object name=\""<<item<<
+			    "\" exists on path=\""<<GetResolvedPath ("")<<"\""
+			    " but is null.");
+	      return;
+	    }
+	  m_workStack.push_back (item);
+	  DoResolve (pathLeft, object);
+	  m_workStack.pop_back ();
+	}
+      // attempt to cast to an object vector.
+      const ObjectVectorChecker *vectorChecker = dynamic_cast<const ObjectVectorChecker *> (PeekPointer (info.checker));
+      if (vectorChecker != 0)
+	{
+	  NS_LOG_DEBUG ("GetAttribute(vector)="<<item<<" on path="<<GetResolvedPath (""));
+	  ObjectVector vector = root->GetAttribute (item);
+	  m_workStack.push_back (item);
+	  DoArrayResolve (pathLeft, vector);
+	  m_workStack.pop_back ();
+	}
+      // this could be anything else and we don't know what to do with it.
+      // So, we just ignore it.
+    }
+}
+
+void 
+Resolver::DoArrayResolve (std::string path, const ObjectVector &vector)
+{
+  NS_ASSERT (path != "");
+  std::string::size_type pos = path.find ("/");
+  if (pos != 0)
+    {
+      NS_FATAL_ERROR ("path does not start with a \"/\": \""<<path<<"\"");
+      return;
+    }
+  std::string::size_type next = path.find ("/", 1);
+  if (next == std::string::npos)
+    {
+      NS_LOG_DEBUG ("vector path includes no index data on path=\""<<path<<"\"");
+      return;
+    }
+  std::string item = path.substr (1, next-1);
+  std::string pathLeft = path.substr (next, path.size ()-next);
+
+  ArrayMatcher matcher = ArrayMatcher (item);
+  for (uint32_t i = 0; i < vector.GetN (); i++)
+    {
+      if (matcher.Matches (i))
+	{
+	  std::ostringstream oss;
+	  oss << i;
+	  m_workStack.push_back (oss.str ());
+	  DoResolve (pathLeft, vector.Get (i));
+	  m_workStack.pop_back ();
+	}
+    }
+}
+
+
+class ConfigImpl 
+{
+public:
+  void Set (std::string path, Attribute value);
+  void Connect (std::string path, const CallbackBase &cb);
+  void Disconnect (std::string path, const CallbackBase &cb);
+
+  void RegisterRootNamespaceObject (Ptr<Object> obj);
+  void UnregisterRootNamespaceObject (Ptr<Object> obj);
+  
+private:
+  typedef std::vector<Ptr<Object> > Roots;
+  Roots m_roots;
+};
+
+void 
+ConfigImpl::Set (std::string path, Attribute value)
+{
+  class SetResolver : public Resolver 
+  {
+  public:
+    SetResolver (std::string path, Attribute value)
+      : Resolver (path),
+	m_value (value) {}
+  private:
+    virtual void DoOne (Ptr<Object> object, std::string name) {
+      object->SetAttribute (name, m_value);
+    }
+    Attribute m_value;
+  } resolver = SetResolver (path, value);
+  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
+    {
+      resolver.Resolve (*i);
+    }
+}
+void 
+ConfigImpl::Connect (std::string path, const CallbackBase &cb)
+{
+  class ConnectResolver : public Resolver 
+  {
+  public:
+    ConnectResolver (std::string path, const CallbackBase &cb)
+      : Resolver (path),
+	m_cb (cb) {}
+  private:
+    virtual void DoOne (Ptr<Object> object, std::string name) {
+      object->TraceSourceConnect (name, m_cb);
+    }
+    CallbackBase m_cb;
+  } resolver = ConnectResolver (path, cb);
+  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
+    {
+      resolver.Resolve (*i);
+    }
+}
+void 
+ConfigImpl::Disconnect (std::string path, const CallbackBase &cb)
+{
+  class DisconnectResolver : public Resolver 
+  {
+  public:
+    DisconnectResolver (std::string path, const CallbackBase &cb)
+      : Resolver (path),
+	m_cb (cb) {}
+  private:
+    virtual void DoOne (Ptr<Object> object, std::string name) {
+      object->TraceSourceDisconnect (name, m_cb);
+    }
+    CallbackBase m_cb;
+  } resolver = DisconnectResolver (path, cb);
+  for (Roots::const_iterator i = m_roots.begin (); i != m_roots.end (); i++)
+    {
+      resolver.Resolve (*i);
+    }
+}
+void 
+ConfigImpl::RegisterRootNamespaceObject (Ptr<Object> obj)
+{
+  m_roots.push_back (obj);
+}
+
+void 
+ConfigImpl::UnregisterRootNamespaceObject (Ptr<Object> obj)
+{
+  for (std::vector<Ptr<Object> >::iterator i = m_roots.begin (); i != m_roots.end (); i++)
+    {
+      if (*i == obj)
+	{
+	  m_roots.erase (i);
+	  return;
+	}
+    }
+}
+
+
+namespace Config {
+
+void Set (std::string path, Attribute value)
+{
+  Singleton<ConfigImpl>::Get ()->Set (path, value);
+}
+void SetDefault (std::string name, Attribute value)
+{
+  AttributeList::GetGlobal ()->Set (name, value);
+}
+void SetGlobal (std::string name, Attribute value)
+{
+  GlobalValue::Bind (name, value);
+}
+void Connect (std::string path, const CallbackBase &cb)
+{
+  Singleton<ConfigImpl>::Get ()->Connect (path, cb);
+}
+void Disconnect (std::string path, const CallbackBase &cb)
+{
+  Singleton<ConfigImpl>::Get ()->Disconnect (path, cb);
+}
+
+void RegisterRootNamespaceObject (Ptr<Object> obj)
+{
+  Singleton<ConfigImpl>::Get ()->RegisterRootNamespaceObject (obj);
+}
+
+void Unregister (Ptr<Object> obj)
+{
+  Singleton<ConfigImpl>::Get ()->UnregisterRootNamespaceObject (obj);
+}
+
+} // namespace Config
+
+} // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+#include "integer.h"
+
+namespace ns3 {
+
+class MyNode : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  void AddNodeA (Ptr<MyNode> a);
+  void AddNodeB (Ptr<MyNode> b);
+
+  void SetNodeA (Ptr<MyNode> a);
+  void SetNodeB (Ptr<MyNode> b);
+
+  int8_t GetA (void) const;
+  int8_t GetB (void) const;
+
+private:
+  std::vector<Ptr<MyNode> > m_nodesA;
+  std::vector<Ptr<MyNode> > m_nodesB;
+  Ptr<MyNode> m_nodeA;
+  Ptr<MyNode> m_nodeB;
+  int8_t m_a;
+  int8_t m_b;
+};
+
+TypeId MyNode::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("MyNode")
+    .SetParent<Object> ()
+    .AddAttribute ("NodesA", "",
+		   ObjectVector (),
+		   MakeObjectVectorAccessor (&MyNode::m_nodesA),
+		   MakeObjectVectorChecker ())
+    .AddAttribute ("NodesB", "",
+		   ObjectVector (),
+		   MakeObjectVectorAccessor (&MyNode::m_nodesB),
+		   MakeObjectVectorChecker ())
+    .AddAttribute ("NodeA", "",
+		   Ptr<MyNode> (0),
+		   MakePtrAccessor (&MyNode::m_nodeA),
+		   MakePtrChecker<MyNode> ())
+    .AddAttribute ("NodeB", "",
+		   Ptr<MyNode> (0),
+		   MakePtrAccessor (&MyNode::m_nodeB),
+		   MakePtrChecker<MyNode> ())
+    .AddAttribute ("A", "",
+		   Integer (10),
+		   MakeIntegerAccessor (&MyNode::m_a),
+		   MakeIntegerChecker<int8_t> ())
+    .AddAttribute ("B", "",
+		   Integer (9),
+		   MakeIntegerAccessor (&MyNode::m_b),
+		   MakeIntegerChecker<int8_t> ())
+    ;
+  return tid;
+}
+
+void
+MyNode::SetNodeA (Ptr<MyNode> a)
+{
+  m_nodeA = a;
+}
+void
+MyNode::SetNodeB (Ptr<MyNode> b)
+{
+  m_nodeB = b;
+}
+void 
+MyNode::AddNodeA (Ptr<MyNode> a)
+{
+  m_nodesA.push_back (a);
+}
+void 
+MyNode::AddNodeB (Ptr<MyNode> b)
+{
+  m_nodesB.push_back (b);
+}
+int8_t 
+MyNode::GetA (void) const
+{
+  return m_a;
+}
+int8_t 
+MyNode::GetB (void) const
+{
+  return m_b;
+}
+
+
+class ConfigTest : public Test
+{
+public:
+  ConfigTest ();
+  virtual bool RunTests (void);
+};
+
+static ConfigTest g_configTestUnique;
+
+ConfigTest::ConfigTest ()
+  : Test ("Config")
+{}
+
+bool
+ConfigTest::RunTests (void)
+{
+  bool result = true;
+
+  Ptr<MyNode> root = CreateObject<MyNode> ();
+  Config::RegisterRootNamespaceObject (root);
+  Config::Set ("/A", Integer (1));
+  Config::Set ("/B", Integer (-1));
+  Integer v = root->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 1);
+  v = root->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -1);
+
+  Ptr<MyNode> a = CreateObject<MyNode> ();
+  root->SetNodeA (a);
+  Config::Set ("/NodeA/A", Integer (2));
+  Config::Set ("/NodeA/B", Integer (-2));
+  v = a->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 2);
+  v = a->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -2);
+  Config::Set ("/NodeB/A", Integer (3));
+  Config::Set ("/NodeB/B", Integer (-3));
+  v = a->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 2);
+  v = a->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -2);
+
+  Ptr<MyNode> b = CreateObject<MyNode> ();
+  a->SetNodeB (b);
+  Config::Set ("/NodeA/NodeB/A", Integer (4));
+  Config::Set ("/NodeA/NodeB/B", Integer (-4));
+  v = b->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 4);
+  v = b->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -4);
+
+  Ptr<MyNode> c = CreateObject<MyNode> ();
+  root->SetNodeB (c);
+  Config::Set ("/NodeB/A", Integer (5));
+  Config::Set ("/NodeB/B", Integer (-5));
+  v = c->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 5);
+  v = c->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -5);
+
+
+  Ptr<MyNode> d0 = CreateObject<MyNode> ();
+  Ptr<MyNode> d1 = CreateObject<MyNode> ();
+  Ptr<MyNode> d2 = CreateObject<MyNode> ();
+  Ptr<MyNode> d3 = CreateObject<MyNode> ();
+  b->AddNodeB (d0);
+  b->AddNodeB (d1);
+  b->AddNodeB (d2);
+  b->AddNodeB (d3);
+  Config::Set ("/NodeA/NodeB/NodesB/0/A", Integer (-11));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -11);
+  v = d0->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 9);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 10);
+  v = d1->GetAttribute ("B");
+  NS_TEST_ASSERT_EQUAL (v.Get (), 9);
+  Config::Set ("/NodeA/NodeB/NodesB/0|1/A", Integer (-12));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -12);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -12);
+  Config::Set ("/NodeA/NodeB/NodesB/|0|1|/A", Integer (-13));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -13);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -13);
+  Config::Set ("/NodeA/NodeB/NodesB/[0-2]/A", Integer (-14));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -14);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -14);
+  v = d2->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -14);
+  Config::Set ("/NodeA/NodeB/NodesB/[1-3]/A", Integer (-15));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -14);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -15);
+  v = d2->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -15);
+  v = d3->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -15);
+  Config::Set ("/NodeA/NodeB/NodesB/[0-1]|3/A", Integer (-16));
+  v = d0->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -16);
+  v = d1->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -16);
+  v = d2->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -15);
+  v = d3->GetAttribute ("A");
+  NS_TEST_ASSERT_EQUAL (v.Get (), -16);
+
+
+
+  return result;
+}
+
+} // namespace ns3
+
+
+#endif /* RUN_SELF_TEST */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/config.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,25 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "attribute.h"
+#include "ptr.h"
+#include "object.h"
+#include <string>
+
+namespace ns3 {
+
+namespace Config {
+
+void Set (std::string path, Attribute value);
+void SetDefault (std::string name, Attribute value);
+void SetGlobal (std::string name, Attribute value);
+void Connect (std::string path, const CallbackBase &cb);
+void Disconnect (std::string path, const CallbackBase &cb);
+
+void RegisterRootNamespaceObject (Ptr<Object> obj);
+
+} // namespace Config
+
+} // namespace ns3
+
+#endif /* CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/double.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,64 @@
+#include "double.h"
+#include "object.h"
+#include <sstream>
+
+namespace ns3 {
+
+Double::Double ()
+{}
+Double::Double (double value)
+  : m_value (value)
+{}
+void 
+Double::Set (double value)
+{
+  m_value = value;
+}
+double 
+Double::Get (void) const
+{
+  return m_value;
+}
+Double::operator double () const
+{
+  return m_value;
+}
+std::ostream & operator << (std::ostream &os, const Double &value)
+{
+  os << value.Get ();
+  return os;
+}
+std::istream & operator >> (std::istream &is, Double &value)
+{
+  double v;
+  is >> v;
+  value.Set (v);
+  return is;
+}
+
+ATTRIBUTE_VALUE_IMPLEMENT (Double);
+  ATTRIBUTE_CONVERTER_IMPLEMENT (Double);
+
+Ptr<const AttributeChecker> MakeDoubleChecker (double min, double max)
+{
+  struct Checker : public AttributeChecker
+  {
+    Checker (double minValue, double maxValue)
+      : m_minValue (minValue),
+      m_maxValue (maxValue) {}
+    virtual bool Check (Attribute value) const {
+      const DoubleValue *v = value.DynCast<const DoubleValue *> ();
+      if (v == 0)
+	{
+	  return false;
+	}
+      return v->Get () >= m_minValue && v->Get () <= m_maxValue;
+    }
+    double m_minValue;
+    double m_maxValue;
+  } *checker = new Checker (min, max);
+  return Ptr<const AttributeChecker> (checker, false);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/double.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,62 @@
+#ifndef FP_VALUE_H
+#define FP_VALUE_H
+
+#include "attribute.h"
+#include "attribute-helper.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class Double
+{
+public:
+  Double ();
+  Double (double value);
+
+  void Set (double value);
+  double Get (void) const;
+
+  operator double () const;
+
+  ATTRIBUTE_CONVERTER_DEFINE (Double);
+private:
+  double m_value;
+};
+
+std::ostream & operator << (std::ostream &os, const Double &value);
+std::istream & operator >> (std::istream &is, Double &value);
+
+ATTRIBUTE_VALUE_DEFINE (Double);
+ATTRIBUTE_ACCESSOR_DEFINE (Double);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeDoubleChecker (void);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeDoubleChecker (double min);
+
+Ptr<const AttributeChecker> MakeDoubleChecker (double min, double max);
+
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+Ptr<const AttributeChecker> MakeDoubleChecker (void)
+{
+  return MakeDoubleChecker (-std::numeric_limits<T>::max (),
+			    std::numeric_limits<T>::max ());
+}
+
+template <typename T>
+Ptr<const AttributeChecker> MakeDoubleChecker (double min)
+{
+  return MakeDoubleChecker (min,
+			    std::numeric_limits<T>::max ());
+}
+
+} // namespace ns3
+
+
+#endif /* FP_VALUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/enum.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,182 @@
+#include "enum.h"
+#include "fatal-error.h"
+#include <sstream>
+
+namespace ns3 {
+
+
+Enum::Enum (int v)
+  : m_v (v)
+{}
+void 
+Enum::Set (int v)
+{
+  m_v = v;
+}
+int 
+Enum::Get (void) const
+{
+  return m_v;
+}
+
+Attribute
+Enum::Copy (void) const
+{
+  return Attribute::Create<Enum> (*this);
+}
+std::string 
+Enum::SerializeToString (Ptr<const AttributeChecker> checker) const
+{
+  const EnumChecker *p = dynamic_cast<const EnumChecker *> (PeekPointer (checker));
+  NS_ASSERT (p != 0);
+  for (EnumChecker::ValueSet::const_iterator i = p->m_valueSet.begin (); i != p->m_valueSet.end (); i++)
+    {
+      if (i->first == m_v)
+	{
+	  return i->second;
+	}
+    }
+  
+  NS_FATAL_ERROR ("The user has set an invalid C++ value in this Enum");
+  // quiet compiler.
+  return "";
+}
+bool 
+Enum::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
+{
+  const EnumChecker *p = dynamic_cast<const EnumChecker *> (PeekPointer (checker));
+  NS_ASSERT (p != 0);
+  for (EnumChecker::ValueSet::const_iterator i = p->m_valueSet.begin (); i != p->m_valueSet.end (); i++)
+    {
+      if (i->second == value)
+	{
+	  m_v = i->first;
+	  return true;
+	}
+    }
+  return false;
+}
+
+Enum::Enum (Attribute value)
+{
+  const Enum *v = value.DynCast<const Enum *> ();
+  if (v == 0)
+    {
+      NS_FATAL_ERROR ("assigning non-Enum value to Enum value.");
+    }
+  m_v = v->m_v;
+}
+Enum::operator Attribute () const
+{
+  return Attribute::Create<Enum> (*this);
+}
+
+
+
+EnumChecker::EnumChecker ()
+{}
+
+void 
+EnumChecker::AddDefault (int v, std::string name)
+{
+  m_valueSet.push_front (std::make_pair (v, name));
+}
+void 
+EnumChecker::Add (int v, std::string name)
+{
+  m_valueSet.push_back (std::make_pair (v, name));
+}
+bool 
+EnumChecker::Check (Attribute value) const
+{
+  const Enum *p = value.DynCast<const Enum *> ();
+  if (p == 0)
+    {
+      return false;
+    }
+  for (ValueSet::const_iterator i = m_valueSet.begin (); i != m_valueSet.end (); i++)
+    {
+      if (i->first == p->Get ())
+	{
+	  return true;
+	}
+    }
+  return false;
+}
+
+Ptr<const AttributeChecker> 
+MakeEnumChecker (int v1, std::string n1,
+		 int v2, std::string n2,
+		 int v3, std::string n3,
+		 int v4, std::string n4,
+		 int v5, std::string n5,
+		 int v6, std::string n6,
+		 int v7, std::string n7,
+		 int v8, std::string n8,
+		 int v9, std::string n9,
+		 int v10, std::string n10,
+		 int v11, std::string n11,
+		 int v12, std::string n12)
+{
+  Ptr<EnumChecker> checker = Create<EnumChecker> ();
+  checker->AddDefault (v1, n1);
+  if (n2 == "")
+    {
+      return checker;
+    }
+  checker->Add (v2, n2);
+  if (n3 == "")
+    {
+      return checker;
+    }
+  checker->Add (v3, n3);
+  if (n4 == "")
+    {
+      return checker;
+    }
+  checker->Add (v4, n4);
+  if (n5 == "")
+    {
+      return checker;
+    }
+  checker->Add (v5, n5);
+  if (n6 == "")
+    {
+      return checker;
+    }
+  checker->Add (v6, n6);
+  if (n7 == "")
+    {
+      return checker;
+    }
+  checker->Add (v7, n7);
+  if (n8 == "")
+    {
+      return checker;
+    }
+  checker->Add (v8, n8);
+  if (n9 == "")
+    {
+      return checker;
+    }
+  checker->Add (v9, n9);
+  if (n10 == "")
+    {
+      return checker;
+    }
+  checker->Add (v10, n10);
+  if (n11 == "")
+    {
+      return checker;
+    }
+  checker->Add (v11, n11);
+  if (n12 == "")
+    {
+      return checker;
+    }
+  checker->Add (v12, n12);
+  return checker;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/enum.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,81 @@
+#ifndef ENUM_VALUE_H
+#define ENUM_VALUE_H
+
+#include "attribute.h"
+#include "attribute-accessor-helper.h"
+#include <list>
+
+namespace ns3 {
+
+class Enum : public AttributeValue
+{
+public:
+  Enum (int v);
+  void Set (int v);
+  int Get (void) const;
+
+  virtual Attribute Copy (void) const;
+  virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
+  virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
+
+  Enum (Attribute value);
+  operator Attribute () const;
+private:
+  int m_v;
+};
+
+class EnumChecker : public AttributeChecker
+{
+public:
+  EnumChecker ();
+
+  void AddDefault (int v, std::string name);
+  void Add (int v, std::string name);
+
+  virtual bool Check (Attribute value) const;
+
+private:
+  friend class Enum;
+  typedef std::list<std::pair<int,std::string> > ValueSet;
+  ValueSet m_valueSet;
+};
+
+template <typename T1>
+Ptr<const AttributeAccessor> MakeEnumAccessor (T1 a1);
+
+template <typename T1, typename T2>
+Ptr<const AttributeAccessor> MakeEnumAccessor (T1 a1, T2 a2);
+
+Ptr<const AttributeChecker> MakeEnumChecker (int v1, std::string n1,
+					     int v2 = 0, std::string n2 = "",
+					     int v3 = 0, std::string n3 = "",
+					     int v4 = 0, std::string n4 = "",
+					     int v5 = 0, std::string n5 = "",
+					     int v6 = 0, std::string n6 = "",
+					     int v7 = 0, std::string n7 = "",
+					     int v8 = 0, std::string n8 = "",
+					     int v9 = 0, std::string n9 = "",
+					     int v10 = 0, std::string n10 = "",
+					     int v11 = 0, std::string n11 = "",
+					     int v12 = 0, std::string n12 = "");
+
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T1>
+Ptr<const AttributeAccessor> MakeEnumAccessor (T1 a1)
+{
+  return MakeAccessorHelper<Enum> (a1);
+}
+
+template <typename T1, typename T2>
+Ptr<const AttributeAccessor> MakeEnumAccessor (T1 a1, T2 a2)
+{
+  return MakeAccessorHelper<Enum> (a1, a2);
+}
+
+} // namespace ns3
+
+#endif /* ENUM_VALUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/global-value.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,125 @@
+#include "global-value.h"
+#include "fatal-error.h"
+#include "attribute.h"
+
+namespace ns3 {
+
+GlobalValue::GlobalValue (std::string name, std::string help,
+			  Attribute initialValue,
+			  Ptr<const AttributeChecker> checker)
+  : m_name (name),
+    m_help (help),
+    m_initialValue (initialValue),
+    m_checker (checker)
+{
+  if (m_checker == 0)
+    {
+      NS_FATAL_ERROR ("Checker should no be zero.");
+    }
+  GetVector ()->push_back (this);
+}
+
+std::string 
+GlobalValue::GetName (void) const
+{
+  return m_name;
+}
+std::string 
+GlobalValue::GetHelp (void) const
+{
+  return m_help;
+}
+Attribute 
+GlobalValue::GetValue (void) const
+{
+  return m_initialValue;
+}
+Ptr<const AttributeChecker> 
+GlobalValue::GetChecker (void) const
+{
+  return m_checker;
+}
+  
+void 
+GlobalValue::SetValue (Attribute value)
+{
+  if (!m_checker->Check (value))
+    {
+      NS_FATAL_ERROR ("Invalid new value.");
+    }
+  m_initialValue = value;
+}
+
+void 
+GlobalValue::Bind (std::string name, Attribute value)
+{
+  for (Iterator i = Begin (); i != End (); i++)
+    {
+      if ((*i)->GetName () == name)
+	{
+	  (*i)->SetValue (value);
+	  return;
+	}
+    }
+}
+GlobalValue::Iterator 
+GlobalValue::Begin (void)
+{
+  return GetVector ()->begin ();
+}
+GlobalValue::Iterator 
+GlobalValue::End (void)
+{
+  return GetVector ()->end ();
+}
+GlobalValue::Vector *
+GlobalValue::GetVector (void)
+{
+  static Vector vector;
+  return &vector;
+}
+
+} // namespace ns3
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+#include "uinteger.h"
+
+namespace {
+
+static ns3::GlobalValue g_uint = ns3::GlobalValue ("TestUint", "help text",
+						     ns3::Uinteger (10),
+						     ns3::MakeUintegerChecker<uint32_t> ());
+
+}
+
+namespace ns3 {
+
+class GlobalValueTests : public Test
+{
+public:
+  GlobalValueTests ();
+  virtual bool RunTests (void);
+private:
+};
+
+
+GlobalValueTests::GlobalValueTests ()
+  : Test ("GlobalValue")
+{}
+bool 
+GlobalValueTests::RunTests (void)
+{
+  bool result = true;
+
+  NS_TEST_ASSERT_EQUAL (10, Uinteger (g_uint.GetValue ()).Get ());
+
+  return result;
+}
+
+static GlobalValueTests g_initialValueTests;
+
+} // namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/global-value.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,43 @@
+#ifndef GLOBAL_VALUE_H
+#define GLOBAL_VALUE_H
+
+#include <string>
+#include <vector>
+#include "ptr.h"
+#include "attribute.h"
+
+
+namespace ns3 {
+
+class GlobalValue
+{
+  typedef std::vector<GlobalValue *> Vector;
+public:
+  typedef Vector::const_iterator Iterator;
+
+  GlobalValue (std::string name, std::string help,
+		Attribute initialValue,
+		Ptr<const AttributeChecker> checker);
+
+  std::string GetName (void) const;
+  std::string GetHelp (void) const;
+  Attribute GetValue (void) const;
+  Ptr<const AttributeChecker> GetChecker (void) const;
+  
+  void SetValue (Attribute value);
+
+  static void Bind (std::string name, Attribute value);
+
+  static Iterator Begin (void);
+  static Iterator End (void);
+private:
+  static Vector *GetVector (void);
+  std::string m_name;
+  std::string m_help;
+  Attribute m_initialValue;
+  Ptr<const AttributeChecker> m_checker;
+};
+
+} // namespace ns3
+
+#endif /* GLOBAL_VALUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/integer.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,70 @@
+#include "integer.h"
+#include "fatal-error.h"
+#include <sstream>
+
+namespace ns3 {
+
+Integer::Integer (int64_t value)
+  : m_value (value)
+{}
+Integer::Integer ()
+  : m_value (0)
+{}
+void 
+Integer::Set (int64_t value)
+{
+  m_value = value;
+}
+int64_t 
+Integer::Get (void) const
+{
+  return m_value;
+}
+
+Integer::operator int64_t () const
+{
+  return m_value;
+}
+
+ATTRIBUTE_VALUE_IMPLEMENT (Integer);
+
+std::ostream &operator << (std::ostream &os, const Integer &integer)
+{
+  os << integer.Get ();
+  return os;
+}
+std::istream &operator >> (std::istream &is, Integer &integer)
+{
+  int64_t v;
+  is >> v;
+  integer.Set (v);
+  return is;
+}
+
+ATTRIBUTE_CONVERTER_IMPLEMENT (Integer);
+
+
+Ptr<const AttributeChecker>
+MakeIntegerChecker (int64_t min, int64_t max)
+{
+  struct IntegerChecker : public AttributeChecker
+  {
+    IntegerChecker (int64_t minValue, int64_t maxValue)
+      : m_minValue (minValue),
+      m_maxValue (maxValue) {}
+    virtual bool Check (Attribute value) const {
+      const IntegerValue *v = value.DynCast<const IntegerValue *> ();
+      if (v == 0)
+	{
+	  return false;
+	}
+      return v->Get ().Get () >= m_minValue && v->Get ().Get() <= m_maxValue;
+    }
+    int64_t m_minValue;
+    int64_t m_maxValue;
+  } *checker = new IntegerChecker (min, max);
+  return Ptr<AttributeChecker> (checker, false);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/integer.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,60 @@
+#ifndef INTEGER_H
+#define INTEGER_H
+
+#include "attribute.h"
+#include "attribute-helper.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class Integer
+{
+public:
+  Integer (int64_t value);
+  Integer ();
+  void Set (int64_t value);
+  int64_t Get (void) const;
+
+  operator int64_t () const;
+  ATTRIBUTE_CONVERTER_DEFINE (Integer);
+private:
+  int64_t m_value;
+};
+
+std::ostream &operator << (std::ostream &os, const Integer &integer);
+std::istream &operator >> (std::istream &is, Integer &integer);
+
+ATTRIBUTE_VALUE_DEFINE(Integer);
+ATTRIBUTE_ACCESSOR_DEFINE(Integer);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeIntegerChecker (void);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeIntegerChecker (int64_t min);
+
+Ptr<const AttributeChecker> MakeIntegerChecker (int64_t min, int64_t max);
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+Ptr<const AttributeChecker>
+MakeIntegerChecker (int64_t min)
+{
+  return MakeIntegerChecker (min,
+			     std::numeric_limits<T>::max ());
+}
+
+template <typename T>
+Ptr<const AttributeChecker>
+MakeIntegerChecker (void)
+{
+  return MakeIntegerChecker (std::numeric_limits<T>::min (),
+			     std::numeric_limits<T>::max ());
+}
+
+} // namespace ns3
+
+#endif /* INTEGER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-base.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,3 @@
+#include "object-base.h"
+
+ns3::ObjectBase::~ObjectBase () {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-base.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,20 @@
+#ifndef OBJECT_BASE_H
+#define OBJECT_BASE_H
+
+namespace ns3 {
+
+/**
+ * This base class is really used only to make sure that 
+ * every subclass has RTTI information and that they all
+ * share a single base class to allow us to make type 
+ * checks across all these types.
+ */
+class ObjectBase
+{
+public:
+  virtual ~ObjectBase ();
+};
+
+} // namespace ns3
+
+#endif /* OBJECT_BASE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-factory.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,43 @@
+#include "object-factory.h"
+#include <sstream>
+
+namespace ns3 {
+
+ObjectFactory::ObjectFactory ()
+{}
+
+void 
+ObjectFactory::SetTypeId (TypeId tid)
+{
+  m_tid = tid;
+}
+void 
+ObjectFactory::SetTypeId (std::string tid)
+{
+  m_tid = TypeId::LookupByName (tid);
+}
+void 
+ObjectFactory::SetTypeId (const char *tid)
+{
+  m_tid = TypeId::LookupByName (tid);
+}
+void 
+ObjectFactory::Set (std::string name, Attribute value)
+{
+  m_parameters.SetWithTid (m_tid, name, value);
+}
+
+TypeId 
+ObjectFactory::GetTypeId (void) const
+{
+  return m_tid;
+}
+
+Ptr<Object> 
+ObjectFactory::Create (void) const
+{
+  Ptr<Object> object = m_tid.CreateObject (m_parameters);
+  return object;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-factory.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,43 @@
+#ifndef OBJECT_FACTORY_H
+#define OBJECT_FACTORY_H
+
+#include "attribute.h"
+#include "object.h"
+
+namespace ns3 {
+
+class ObjectFactory
+{
+public:
+  ObjectFactory ();
+
+  void SetTypeId (TypeId tid);
+  void SetTypeId (std::string tid);
+  void SetTypeId (const char *tid);
+  void Set (std::string name, Attribute value);
+
+  TypeId GetTypeId (void) const;
+
+  Ptr<Object> Create (void) const;
+  template <typename T>
+  Ptr<T> Create (void) const;
+
+private:
+  TypeId m_tid;
+  AttributeList m_parameters;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+Ptr<T> 
+ObjectFactory::Create (void) const
+{
+  return Create ()->GetObject<T> ();
+}
+
+} // namespace ns3
+
+#endif /* OBJECT_FACTORY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-vector.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,110 @@
+#include "object-vector.h"
+
+namespace ns3 {
+
+ObjectVector::ObjectVector ()
+{}
+
+ObjectVector::Iterator 
+ObjectVector::Begin (void) const
+{
+  return m_objects.begin ();
+}
+ObjectVector::Iterator 
+ObjectVector::End (void) const
+{
+  return m_objects.end ();
+}
+uint32_t 
+ObjectVector::GetN (void) const
+{
+  return m_objects.size ();
+}
+Ptr<Object> 
+ObjectVector::Get (uint32_t i) const
+{
+  return m_objects[i];
+}
+
+ObjectVector::ObjectVector (Attribute value)
+{
+  const ObjectVectorValue *v = value.DynCast<const ObjectVectorValue *> ();
+  if (v == 0)
+    {
+      NS_FATAL_ERROR ("Expected value of type ObjectVectorValue.");
+    }
+  *this = v->Get ();
+}
+
+ObjectVector::operator Attribute () const
+{
+  return Attribute::Create<ObjectVectorValue> ();
+}
+
+ObjectVectorValue::ObjectVectorValue ()
+  : m_vector ()
+{}
+
+ObjectVectorValue::ObjectVectorValue (const ObjectVector &vector)
+  : m_vector (vector)
+{}
+
+ObjectVector 
+ObjectVectorValue::Get (void) const
+{
+  return m_vector;
+}
+
+Attribute 
+ObjectVectorValue::Copy (void) const
+{
+  return Attribute::Create<ObjectVectorValue> (*this);
+}
+std::string 
+ObjectVectorValue::SerializeToString (Ptr<const AttributeChecker> checker) const
+{
+  // XXX
+  return "";
+}
+bool 
+ObjectVectorValue::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
+{
+  // XXX ?? Can we implement this correctly ?? I doubt it very much.
+  return true;
+}
+
+bool 
+ObjectVectorAccessor::Set (ObjectBase * object, Attribute value) const
+{
+  // not allowed.
+  return false;
+}
+bool 
+ObjectVectorAccessor::Get (const ObjectBase * object, Attribute value) const
+{
+  ObjectVectorValue *v = value.DynCast<ObjectVectorValue *> ();
+  if (v == 0)
+    {
+      return false;
+    }
+  v->m_vector.m_objects.clear ();
+  uint32_t n;
+  bool ok = DoGetN (object, &n);
+  if (!ok)
+    {
+      return false;
+    }
+  for (uint32_t i = 0; i < n; i++)
+    {
+      Ptr<Object> o = DoGet (object, i);
+      v->m_vector.m_objects.push_back (o);
+    }
+  return true;
+}
+Ptr<const AttributeChecker> 
+MakeObjectVectorChecker (void)
+{
+  return MakeSimpleAttributeChecker<ObjectVectorValue,ObjectVectorChecker> ();
+}
+
+} // name
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/object-vector.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,155 @@
+#ifndef OBJECT_VECTOR_H
+#define OBJECT_VECTOR_H
+
+#include <vector>
+#include "object.h"
+#include "ptr.h"
+#include "attribute.h"
+
+namespace ns3 {
+
+class ObjectVector
+{
+public:
+  typedef std::vector<Ptr<Object> >::const_iterator Iterator;
+
+  ObjectVector ();
+
+  Iterator Begin (void) const;
+  Iterator End (void) const;
+  uint32_t GetN (void) const;
+  Ptr<Object> Get (uint32_t i) const;
+
+  ObjectVector (Attribute value);
+  operator Attribute () const;
+private:
+  friend class ObjectVectorAccessor;
+  std::vector<Ptr<Object> > m_objects;
+};
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (U T::*memberVector);
+
+template <typename T, typename U, typename INDEX>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (Ptr<U> (T::*get) (INDEX) const,
+			   INDEX (T::*getN) (void) const);
+
+template <typename T, typename U, typename INDEX>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (INDEX (T::*getN) (void) const,
+			   Ptr<U> (T::*get) (INDEX) const);
+
+
+class ObjectVectorChecker : public AttributeChecker {};
+Ptr<const AttributeChecker> MakeObjectVectorChecker (void);
+
+} // namespace ns3
+
+namespace ns3 {
+
+class ObjectVectorValue : public AttributeValue
+{
+public:
+  ObjectVectorValue ();
+  ObjectVectorValue (const ObjectVector &vector);
+
+  ObjectVector Get (void) const;
+
+  virtual Attribute Copy (void) const;
+  virtual std::string SerializeToString (Ptr<const AttributeChecker> checker) const;
+  virtual bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
+
+private:
+  friend class ObjectVectorAccessor;
+  ObjectVector m_vector;
+};
+
+class ObjectVectorAccessor : public AttributeAccessor
+{
+public:
+  virtual bool Set (ObjectBase * object, Attribute value) const;
+  virtual bool Get (const ObjectBase * object, Attribute value) const;
+private:
+  virtual bool DoGetN (const ObjectBase *object, uint32_t *n) const = 0;
+  virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const = 0;
+};
+
+template <typename T, typename U>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (U T::*memberVector)
+{
+  struct MemberStdContainer : public ObjectVectorAccessor
+  {
+    virtual bool DoGetN (const ObjectBase *object, uint32_t *n) const {
+      const T *obj = dynamic_cast<const T *> (object);
+      if (obj == 0)
+	{
+	  return false;
+	}
+      *n = (obj->*m_memberVector).size ();
+      return true;
+    }
+    virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const {
+      const T *obj = static_cast<const T *> (object);
+      typename U::const_iterator begin = (obj->*m_memberVector).begin ();
+      typename U::const_iterator end = (obj->*m_memberVector).end ();
+      uint32_t k = 0;
+      for (typename U::const_iterator j = begin; j != end; j++, k++)
+	{
+	  if (k == i)
+	    {
+	      return *j;
+	      break;
+	    }
+	}
+      NS_ASSERT (false);
+      // quiet compiler.
+      return 0;
+    }
+    U T::*m_memberVector;
+  } *spec = new MemberStdContainer ();
+  spec->m_memberVector = memberVector;
+  return Ptr<const AttributeAccessor> (spec, false);
+}
+
+template <typename T, typename U, typename INDEX>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (Ptr<U> (T::*get) (INDEX) const,
+			   INDEX (T::*getN) (void) const)
+{
+  struct MemberGetters : public ObjectVectorAccessor
+  {
+    virtual bool DoGetN (const ObjectBase *object, uint32_t *n) const {
+      const T *obj = dynamic_cast<const T *> (object);
+      if (obj == 0)
+	{
+	  return false;
+	}
+      *n = (obj->*m_getN) ();
+      return true;
+    }
+    virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const {
+      const T *obj = static_cast<const T *> (object);
+      return (obj->*m_get) (i);
+    }
+    Ptr<U> (T::*m_get) (INDEX) const;
+    INDEX (T::*m_getN) (void) const;
+  } *spec = new MemberGetters ();
+  spec->m_get = get;
+  spec->m_getN = getN;
+  return Ptr<const AttributeAccessor> (spec, false);
+}
+
+template <typename T, typename U, typename INDEX>
+Ptr<const AttributeAccessor>
+MakeObjectVectorAccessor (INDEX (T::*getN) (void) const,
+			   Ptr<U> (T::*get) (INDEX) const)
+{
+  return MakeObjectVectorAccessor (get, getN);
+}
+
+} // namespace ns3
+
+#endif /* OBJECT_VECTOR_H */
--- a/src/core/object.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/object.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -22,8 +22,12 @@
 #include "assert.h"
 #include "singleton.h"
 #include "trace-resolver.h"
+#include "attribute.h"
+#include "trace-source-accessor.h"
 #include "log.h"
+#include "string.h"
 #include <vector>
+#include <sstream>
 
 NS_LOG_COMPONENT_DEFINE ("Object");
 
@@ -36,25 +40,69 @@
 class IidManager
 {
 public:
+  IidManager ();
   uint16_t AllocateUid (std::string name);
   void SetParent (uint16_t uid, uint16_t parent);
+  void SetTypeName (uint16_t uid, std::string typeName);
+  void SetGroupName (uint16_t uid, std::string groupName);
   void AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments);
   uint16_t GetUid (std::string name) const;
   std::string GetName (uint16_t uid) const;
   uint16_t GetParent (uint16_t uid) const;
+  std::string GetTypeName (uint16_t uid) const;
+  std::string GetGroupName (uint16_t uid) const;
   ns3::CallbackBase GetConstructor (uint16_t uid, uint32_t nArguments);
   bool HasConstructor (uint16_t uid);
   uint32_t GetRegisteredN (void);
   uint16_t GetRegistered (uint32_t i);
+  void AddAttribute (uint16_t uid, 
+                     std::string name,
+                     std::string help, 
+                     uint32_t flags,
+                     ns3::Attribute initialValue,
+                     ns3::Ptr<const ns3::AttributeAccessor> spec,
+                     ns3::Ptr<const ns3::AttributeChecker> checker);
+  uint32_t GetAttributeListN (uint16_t uid) const;
+  std::string GetAttributeName (uint16_t uid, uint32_t i) const;
+  uint32_t GetAttributeFlags (uint16_t uid, uint32_t i) const;
+  ns3::Attribute GetAttributeInitialValue (uint16_t uid, uint32_t i) const;
+  ns3::Ptr<const ns3::AttributeAccessor> GetAttributeAccessor (uint16_t uid, uint32_t i) const;
+  ns3::Ptr<const ns3::AttributeChecker> GetAttributeChecker (uint16_t uid, uint32_t i) const;
+  void AddTraceSource (uint16_t uid,
+                       std::string name, 
+                       std::string help,
+                       ns3::Ptr<const ns3::TraceSourceAccessor> accessor);
+  uint32_t GetTraceSourceN (uint16_t uid) const;
+  std::string GetTraceSourceName (uint16_t uid, uint32_t i) const;
+  std::string GetTraceSourceHelp (uint16_t uid, uint32_t i) const;
+  ns3::Ptr<const ns3::TraceSourceAccessor> GetTraceSourceAccessor (uint16_t uid, uint32_t i) const;
+
 private:
   struct ConstructorInformation {
     ns3::CallbackBase cb;
     uint32_t nArguments;
   };
+  struct AttributeInformation {
+    std::string name;
+    std::string help;
+    uint32_t flags;
+    ns3::Attribute initialValue;
+    ns3::Ptr<const ns3::AttributeAccessor> param;
+    ns3::Ptr<const ns3::AttributeChecker> checker;
+  };
+  struct TraceSourceInformation {
+    std::string name;
+    std::string help;
+    ns3::Ptr<const ns3::TraceSourceAccessor> accessor;
+  };
   struct IidInformation {
     std::string name;
     uint16_t parent;
+    std::string typeName;
+    std::string groupName;
     std::vector<struct ConstructorInformation> constructors;
+    std::vector<struct AttributeInformation> attributes;
+    std::vector<struct TraceSourceInformation> traceSources;
   };
   typedef std::vector<struct IidInformation>::const_iterator Iterator;
 
@@ -63,6 +111,9 @@
   std::vector<struct IidInformation> m_information;
 };
 
+IidManager::IidManager ()
+{}
+
 uint16_t 
 IidManager::AllocateUid (std::string name)
 {
@@ -79,6 +130,8 @@
   struct IidInformation information;
   information.name = name;
   information.parent = 0;
+  information.typeName = "";
+  information.groupName = "";
   m_information.push_back (information);
   uint32_t uid = m_information.size ();
   NS_ASSERT (uid <= 0xffff);
@@ -100,6 +153,19 @@
   information->parent = parent;
 }
 void 
+IidManager::SetTypeName (uint16_t uid, std::string typeName)
+{
+  struct IidInformation *information = LookupInformation (uid);
+  information->typeName = typeName;
+}
+void 
+IidManager::SetGroupName (uint16_t uid, std::string groupName)
+{
+  struct IidInformation *information = LookupInformation (uid);
+  information->groupName = groupName;
+}
+
+void 
 IidManager::AddConstructor (uint16_t uid, ns3::CallbackBase callback, uint32_t nArguments)
 {
   struct IidInformation *information = LookupInformation (uid);
@@ -145,6 +211,19 @@
   struct IidInformation *information = LookupInformation (uid);
   return information->parent;
 }
+std::string 
+IidManager::GetTypeName (uint16_t uid) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  return information->typeName;
+}
+std::string 
+IidManager::GetGroupName (uint16_t uid) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  return information->groupName;
+}
+
 ns3::CallbackBase 
 IidManager::GetConstructor (uint16_t uid, uint32_t nArguments)
 {
@@ -179,6 +258,118 @@
   return i + 1;
 }
 
+void 
+IidManager::AddAttribute (uint16_t uid, 
+                          std::string name,
+                          std::string help, 
+                          uint32_t flags,
+                          ns3::Attribute initialValue,
+                          ns3::Ptr<const ns3::AttributeAccessor> spec,
+                          ns3::Ptr<const ns3::AttributeChecker> checker)
+{
+  struct IidInformation *information = LookupInformation (uid);
+  for (std::vector<struct AttributeInformation>::const_iterator j = information->attributes.begin ();
+       j != information->attributes.end (); j++)
+    {
+      if (j->name == name)
+        {
+          NS_FATAL_ERROR ("Registered the same attribute twice name=\""<<name<<"\" in TypeId=\""<<information->name<<"\"");
+          return;
+        }
+    }
+  struct AttributeInformation param;
+  param.name = name;
+  param.help = help;
+  param.flags = flags;
+  param.initialValue = initialValue;
+  param.param = spec;
+  param.checker = checker;
+  information->attributes.push_back (param);
+}
+
+
+uint32_t 
+IidManager::GetAttributeListN (uint16_t uid) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  return information->attributes.size ();
+}
+std::string 
+IidManager::GetAttributeName (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->attributes.size ());
+  return information->attributes[i].name;
+}
+uint32_t
+IidManager::GetAttributeFlags (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->attributes.size ());
+  return information->attributes[i].flags;
+}
+ns3::Attribute 
+IidManager::GetAttributeInitialValue (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->attributes.size ());
+  return information->attributes[i].initialValue;
+}
+ns3::Ptr<const ns3::AttributeAccessor>
+IidManager::GetAttributeAccessor (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->attributes.size ());
+  return information->attributes[i].param;
+}
+ns3::Ptr<const ns3::AttributeChecker>
+IidManager::GetAttributeChecker (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->attributes.size ());
+  return information->attributes[i].checker;
+}
+
+void 
+IidManager::AddTraceSource (uint16_t uid,
+                            std::string name, 
+                            std::string help,
+                            ns3::Ptr<const ns3::TraceSourceAccessor> accessor)
+{
+  struct IidInformation *information  = LookupInformation (uid);
+  struct TraceSourceInformation source;
+  source.name = name;
+  source.help = help;
+  source.accessor = accessor;
+  information->traceSources.push_back (source);
+}
+uint32_t 
+IidManager::GetTraceSourceN (uint16_t uid) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  return information->traceSources.size ();
+}
+std::string 
+IidManager::GetTraceSourceName (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->traceSources.size ());
+  return information->traceSources[i].name;
+}
+std::string 
+IidManager::GetTraceSourceHelp (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->traceSources.size ());
+  return information->traceSources[i].help;
+}
+ns3::Ptr<const ns3::TraceSourceAccessor> 
+IidManager::GetTraceSourceAccessor (uint16_t uid, uint32_t i) const
+{
+  struct IidInformation *information = LookupInformation (uid);
+  NS_ASSERT (i < information->traceSources.size ());
+  return information->traceSources[i].accessor;
+}
 
 } // anonymous namespace
 
@@ -253,7 +444,11 @@
  *         The TypeId class
  *********************************************************************/
 
-TypeId::TypeId (std::string name)
+TypeId::TypeId ()
+  : m_tid (0)
+{}
+
+TypeId::TypeId (const char * name)
 {
   uint16_t uid = Singleton<IidManager>::Get ()->AllocateUid (name);
   NS_ASSERT (uid != 0);
@@ -273,6 +468,19 @@
   NS_ASSERT (uid != 0);
   return TypeId (uid);
 }
+bool
+TypeId::LookupAttributeByFullName (std::string fullName, struct TypeId::AttributeInfo *info)
+{
+  std::string::size_type pos = fullName.find ("::");
+  if (pos == std::string::npos)
+    {
+      return 0;
+    }
+  std::string tidName = fullName.substr (0, pos);
+  std::string paramName = fullName.substr (pos+2, fullName.size () - (pos+2));
+  TypeId tid = LookupByName (tidName);
+  return tid.LookupAttributeByName (paramName, info);
+}
 uint32_t 
 TypeId::GetRegisteredN (void)
 {
@@ -284,6 +492,55 @@
   return TypeId (Singleton<IidManager>::Get ()->GetRegistered (i));
 }
 
+bool
+TypeId::LookupAttributeByName (std::string name, struct TypeId::AttributeInfo *info) const
+{
+  TypeId tid;
+  TypeId nextTid = *this;
+  do {
+    tid = nextTid;
+    for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
+      {
+        std::string paramName = tid.GetAttributeName (i);
+        if (paramName == name)
+          {
+            info->accessor = tid.GetAttributeAccessor (i);
+            info->flags = tid.GetAttributeFlags (i);
+            info->initialValue = tid.GetAttributeInitialValue (i);
+            info->checker = tid.GetAttributeChecker (i);
+            return true;
+          }
+      }
+    nextTid = tid.GetParent ();
+  } while (nextTid != tid);
+  return false;
+}
+bool
+TypeId::LookupAttributeByPosition (uint32_t i, struct TypeId::AttributeInfo *info) const
+{
+  uint32_t cur = 0;
+  TypeId tid;
+  TypeId nextTid = *this;
+  do {
+    tid = nextTid;
+    for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
+      {
+        if (cur == i)
+          {
+            info->accessor = tid.GetAttributeAccessor (j);
+            info->flags = tid.GetAttributeFlags (j);
+            info->initialValue = tid.GetAttributeInitialValue (j);
+            info->checker = tid.GetAttributeChecker (j);
+            return true;
+          }
+        cur++;
+      }
+    nextTid = tid.GetParent ();
+  } while (nextTid != tid);
+  return false;
+}
+
+
 TypeId 
 TypeId::SetParent (TypeId tid)
 {
@@ -291,12 +548,37 @@
   return *this;
 }
 TypeId 
+TypeId::SetGroupName (std::string groupName)
+{
+  Singleton<IidManager>::Get ()->SetGroupName (m_tid, groupName);
+  return *this;
+}
+TypeId 
+TypeId::SetTypeName (std::string typeName)
+{
+  Singleton<IidManager>::Get ()->SetTypeName (m_tid, typeName);
+  return *this;
+}
+TypeId 
 TypeId::GetParent (void) const
 {
   uint16_t parent = Singleton<IidManager>::Get ()->GetParent (m_tid);
   return TypeId (parent);
 }
 std::string 
+TypeId::GetGroupName (void) const
+{
+  std::string groupName = Singleton<IidManager>::Get ()->GetGroupName (m_tid);
+  return groupName;
+}
+std::string 
+TypeId::GetTypeName (void) const
+{
+  std::string typeName = Singleton<IidManager>::Get ()->GetTypeName (m_tid);
+  return typeName;
+}
+
+std::string 
 TypeId::GetName (void) const
 {
   std::string name = Singleton<IidManager>::Get ()->GetName (m_tid);
@@ -316,22 +598,163 @@
   Singleton<IidManager>::Get ()->AddConstructor (m_tid, cb, nArguments);
 }
 
+TypeId 
+TypeId::AddAttribute (std::string name,
+                      std::string help, 
+                      Attribute initialValue,
+                      Ptr<const AttributeAccessor> param,
+                      Ptr<const AttributeChecker> checker)
+{
+  Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, ATTR_SGC, initialValue, param, checker);
+  return *this;
+}
+
+TypeId 
+TypeId::AddAttribute (std::string name,
+                      std::string help, 
+                      uint32_t flags,
+                      Attribute initialValue,
+                      Ptr<const AttributeAccessor> param,
+                      Ptr<const AttributeChecker> checker)
+{
+  Singleton<IidManager>::Get ()->AddAttribute (m_tid, name, help, flags, initialValue, param, checker);
+  return *this;
+}
+
+
 CallbackBase
-TypeId::LookupConstructor (uint32_t nArguments)
+TypeId::LookupConstructor (uint32_t nArguments) const
 {
   CallbackBase constructor = Singleton<IidManager>::Get ()->GetConstructor (m_tid, nArguments);
   return constructor;
 }
 
 Ptr<Object> 
-TypeId::CreateObject (void)
+TypeId::CreateObject (void) const
+{
+  return CreateObject (AttributeList ());
+}
+Ptr<Object> 
+TypeId::CreateObject (const AttributeList &attributes) const
 {
   CallbackBase cb = LookupConstructor (0);
-  Callback<Ptr<Object> > realCb;
+  Callback<Ptr<Object>,const AttributeList &> realCb;
   realCb.Assign (cb);
-  Ptr<Object> object = realCb ();
-  return object;
+  Ptr<Object> object = realCb (attributes);
+  return object;  
+}
+
+uint32_t 
+TypeId::GetAttributeListN (void) const
+{
+  uint32_t n = Singleton<IidManager>::Get ()->GetAttributeListN (m_tid);
+  return n;
+}
+std::string 
+TypeId::GetAttributeName (uint32_t i) const
+{
+  std::string name = Singleton<IidManager>::Get ()->GetAttributeName (m_tid, i);
+  return name;
+}
+std::string 
+TypeId::GetAttributeFullName (uint32_t i) const
+{
+  return GetName () + "::" + GetAttributeName (i);
+}
+Attribute 
+TypeId::GetAttributeInitialValue (uint32_t i) const
+{
+  Attribute value = Singleton<IidManager>::Get ()->GetAttributeInitialValue (m_tid, i);
+  return value;
+}
+Ptr<const AttributeAccessor>
+TypeId::GetAttributeAccessor (uint32_t i) const
+{
+  // Used exclusively by the Object class.
+  Ptr<const AttributeAccessor> param = Singleton<IidManager>::Get ()->GetAttributeAccessor (m_tid, i);
+  return param;
+}
+uint32_t 
+TypeId::GetAttributeFlags (uint32_t i) const
+{
+  // Used exclusively by the Object class.
+  uint32_t flags = Singleton<IidManager>::Get ()->GetAttributeFlags (m_tid, i);
+  return flags;
+}
+Ptr<const AttributeChecker>
+TypeId::GetAttributeChecker (uint32_t i) const
+{
+  // Used exclusively by the Object class.
+  Ptr<const AttributeChecker> checker = Singleton<IidManager>::Get ()->GetAttributeChecker (m_tid, i);
+  return checker;
+}
+
+uint32_t 
+TypeId::GetTraceSourceN (void) const
+{
+  return Singleton<IidManager>::Get ()->GetTraceSourceN (m_tid);
 }
+std::string 
+TypeId::GetTraceSourceName (uint32_t i) const
+{
+  return Singleton<IidManager>::Get ()->GetTraceSourceName (m_tid, i);
+}
+std::string 
+TypeId::GetTraceSourceHelp (uint32_t i) const
+{
+  return Singleton<IidManager>::Get ()->GetTraceSourceHelp (m_tid, i);
+}
+Ptr<const TraceSourceAccessor> 
+TypeId::GetTraceSourceAccessor (uint32_t i) const
+{
+  return Singleton<IidManager>::Get ()->GetTraceSourceAccessor (m_tid, i);
+}
+
+TypeId 
+TypeId::AddTraceSource (std::string name,
+                        std::string help,
+                        Ptr<const TraceSourceAccessor> accessor)
+{
+  Singleton<IidManager>::Get ()->AddTraceSource (m_tid, name, help, accessor);
+  return *this;
+}
+
+
+Ptr<const TraceSourceAccessor> 
+TypeId::LookupTraceSourceByName (std::string name) const
+{
+  TypeId tid;
+  TypeId nextTid = *this;
+  do {
+    tid = nextTid;
+    for (uint32_t i = 0; i < tid.GetTraceSourceN (); i++)
+      {
+        std::string srcName = tid.GetTraceSourceName (i);
+        if (srcName == name)
+          {
+            return tid.GetTraceSourceAccessor (i);
+          }
+      }
+    nextTid = tid.GetParent ();
+  } while (nextTid != tid);
+  return 0;
+}
+
+std::ostream & operator << (std::ostream &os, TypeId tid)
+{
+  os << tid.GetName ();
+  return os;
+}
+std::istream & operator >> (std::istream &is, TypeId &tid)
+{
+  std::string tidString;
+  is >> tidString;
+  tid = TypeId::LookupByName (tidString);
+  return is;
+}
+
+
+VALUE_HELPER_CPP (TypeId);
 
 bool operator == (TypeId a, TypeId b)
 {
@@ -344,6 +767,217 @@
 }
 
 /*********************************************************************
+ *         The AttributeList container implementation
+ *********************************************************************/
+
+AttributeList::AttributeList ()
+{}
+
+AttributeList::AttributeList (const AttributeList &o)
+{
+  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
+    {
+      struct Attr attr;
+      attr.checker = i->checker;
+      attr.value = i->value.Copy ();
+      m_attributes.push_back (attr);
+    }
+}
+AttributeList &
+AttributeList::operator = (const AttributeList &o)
+{
+  Reset ();
+  for (Attrs::const_iterator i = o.m_attributes.begin (); i != o.m_attributes.end (); i++)
+    {
+      struct Attr attr;
+      attr.checker = i->checker;
+      attr.value = i->value.Copy ();
+      m_attributes.push_back (attr);
+    }
+  return *this;
+}
+AttributeList::~AttributeList ()
+{
+  Reset ();
+}
+
+bool 
+AttributeList::Set (std::string name, Attribute value)
+{
+  struct TypeId::AttributeInfo info;
+  TypeId::LookupAttributeByFullName (name, &info);
+  bool ok = DoSet (&info, value);
+  return ok;
+}
+void 
+AttributeList::SetWithTid (TypeId tid, std::string name, Attribute value)
+{
+  struct TypeId::AttributeInfo info;
+  tid.LookupAttributeByName (name, &info);
+  DoSet (&info, value);
+}
+void 
+AttributeList::SetWithTid (TypeId tid, uint32_t position, Attribute value)
+{
+  struct TypeId::AttributeInfo info;
+  tid.LookupAttributeByPosition (position, &info);
+  DoSet (&info, value);
+}
+
+void
+AttributeList::DoSetOne (Ptr<const AttributeChecker> checker, Attribute value)
+{
+  // get rid of any previous value stored in this
+  // vector of values.
+  for (Attrs::iterator k = m_attributes.begin (); k != m_attributes.end (); k++)
+    {
+      if (k->checker == checker)
+        {
+          m_attributes.erase (k);
+          break;
+        }
+    }
+  // store the new value.
+  struct Attr attr;
+  attr.checker = checker;
+  attr.value = value.Copy ();
+  m_attributes.push_back (attr);
+}
+bool
+AttributeList::DoSet (struct TypeId::AttributeInfo *info, Attribute value)
+{
+  if (info->checker == 0)
+    {
+      return false;
+    }
+  bool ok = info->checker->Check (value);
+  if (!ok)
+    {
+      // attempt to convert to string.
+      const StringValue *str = value.DynCast<const StringValue *> ();
+      if (str == 0)
+        {
+          return false;
+        }
+      // attempt to convert back to value.
+      Attribute v = info->initialValue.Copy ();
+      ok = v.DeserializeFromString (str->Get ().Get (), info->checker);
+      if (!ok)
+        {
+          return false;
+        }
+      ok = info->checker->Check (v);
+      if (!ok)
+        {
+          return false;
+        }
+      value = v;
+    }
+  DoSetOne (info->checker, value);
+  return true;
+}
+void 
+AttributeList::Reset (void)
+{
+  m_attributes.clear ();
+}
+AttributeList *
+AttributeList::GetGlobal (void)
+{
+  return Singleton<AttributeList>::Get ();
+}
+
+std::string
+AttributeList::LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const
+{
+  for (uint32_t i = 0; i < TypeId::GetRegisteredN (); i++)
+    {
+      TypeId tid = TypeId::GetRegistered (i);
+      for (uint32_t j = 0; j < tid.GetAttributeListN (); j++)
+        {
+          if (checker == tid.GetAttributeChecker (j))
+            {
+              return tid.GetAttributeFullName (j);
+            }
+        }
+    }
+  NS_FATAL_ERROR ("Could not find requested Accessor.");
+  // quiet compiler.
+  return "";
+}
+
+std::string 
+AttributeList::SerializeToString (void) const
+{
+  std::ostringstream oss;
+  for (Attrs::const_iterator i = m_attributes.begin (); i != m_attributes.end (); i++)
+    {
+      std::string name = LookupAttributeFullNameByChecker (i->checker);
+      oss << name << "=" << i->value.SerializeToString (i->checker);
+      if (i != m_attributes.end ())
+        {
+          oss << "|";
+        }
+    }  
+  return oss.str ();
+}
+bool 
+AttributeList::DeserializeFromString (std::string str)
+{
+  Reset ();
+
+  std::string::size_type cur;
+  cur = 0;
+  do {
+    std::string::size_type equal = str.find ("=", cur);
+    if (equal == std::string::npos)
+      {
+        // XXX: invalid attribute.
+        break;
+      }
+    else
+      {
+        std::string name = str.substr (cur, equal-cur);
+        struct TypeId::AttributeInfo info;
+        if (!TypeId::LookupAttributeByFullName (name, &info))
+          {
+            // XXX invalid name.
+            break;
+          }
+        else
+          {
+            std::string::size_type next = str.find ("|", cur);
+            std::string value;
+            if (next == std::string::npos)
+              {
+                value = str.substr (equal+1, str.size () - (equal+1));
+                cur = str.size ();
+              }
+            else
+              {
+                value = str.substr (equal+1, next - (equal+1));
+                cur++;
+              }
+            Attribute val = info.initialValue.Copy ();
+            bool ok = val.DeserializeFromString (value, info.checker);
+            if (!ok)
+              {
+                // XXX invalid value
+                break;
+              }
+            else
+              {
+                DoSetOne (info.checker, val);
+              }
+          }
+      }
+  } while (cur != str.size ());
+
+  return true;
+}
+
+
+/*********************************************************************
  *         The Object implementation
  *********************************************************************/
 
@@ -376,6 +1010,185 @@
 {
   m_next = 0;
 }
+void
+Object::Construct (const AttributeList &attributes)
+{
+  // loop over the inheritance tree back to the Object base class.
+  TypeId tid = m_tid;
+  do {
+    // loop over all attributes in object type
+    NS_LOG_DEBUG ("construct tid="<<tid.GetName ()<<", params="<<tid.GetAttributeListN ());
+    for (uint32_t i = 0; i < tid.GetAttributeListN (); i++)
+      {
+        Ptr<const AttributeAccessor> paramSpec = tid.GetAttributeAccessor (i);
+        Attribute initial = tid.GetAttributeInitialValue (i);
+        Ptr<const AttributeChecker> checker = tid.GetAttributeChecker (i);
+        NS_LOG_DEBUG ("try to construct \""<< tid.GetName ()<<"::"<<
+                      tid.GetAttributeName (i)<<"\"");
+        if (!(tid.GetAttributeFlags (i) & TypeId::ATTR_CONSTRUCT))
+          {
+            continue;
+          }
+        bool found = false;
+        // is this attribute stored in this AttributeList instance ?
+        for (AttributeList::Attrs::const_iterator j = attributes.m_attributes.begin ();
+             j != attributes.m_attributes.end (); j++)
+          {
+            if (j->checker == checker)
+              {
+                // We have a matching attribute value.
+                DoSet (paramSpec, initial, checker, j->value);
+                NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+                              tid.GetAttributeName (i)<<"\"");
+                found = true;
+                break;
+              }
+          }
+        if (!found)
+          {
+            // is this attribute stored in the global instance instance ?
+            for (AttributeList::Attrs::const_iterator j = AttributeList::GetGlobal ()->m_attributes.begin ();
+                 j != AttributeList::GetGlobal ()->m_attributes.end (); j++)
+              {
+                if (j->checker == checker)
+                  {
+                    // We have a matching attribute value.
+                    DoSet (paramSpec, initial, checker, j->value);
+                    NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+                                  tid.GetAttributeName (i)<<"\" from global");
+                    found = true;
+                    break;
+                  }
+              }
+          }
+        if (!found)
+          {
+            // No matching attribute value so we set the default value.
+            paramSpec->Set (this, initial);
+            NS_LOG_DEBUG ("construct \""<< tid.GetName ()<<"::"<<
+                          tid.GetAttributeName (i)<<"\" from local");
+          }
+      }
+    tid = tid.GetParent ();
+  } while (tid != Object::GetTypeId ());
+  NotifyConstructionCompleted ();
+}
+bool
+Object::DoSet (Ptr<const AttributeAccessor> spec, Attribute initialValue, 
+               Ptr<const AttributeChecker> checker, Attribute value)
+{
+  bool ok = checker->Check (value);
+  if (!ok)
+    {
+      // attempt to convert to string
+      const StringValue *str = value.DynCast<const StringValue *> ();
+      if (str == 0)
+        {
+          return false;
+        }
+      // attempt to convert back from string.
+      Attribute v = initialValue.Copy ();
+      ok = v.DeserializeFromString (str->Get ().Get (), checker);
+      if (!ok)
+        {
+          return false;
+        }
+      ok = checker->Check (v);
+      if (!ok)
+        {
+          return false;
+        }
+      value = v;
+    }
+  ok = spec->Set (this, value);
+  return ok;
+}
+bool
+Object::SetAttribute (std::string name, Attribute value)
+{
+  struct TypeId::AttributeInfo info;
+  if (!m_tid.LookupAttributeByName (name, &info))
+    {
+      return false;
+    }
+  if (!(info.flags & TypeId::ATTR_SET))
+    {
+      return false;
+    }
+  return DoSet (info.accessor, info.initialValue, info.checker, value);
+}
+bool 
+Object::GetAttribute (std::string name, std::string &value) const
+{
+  struct TypeId::AttributeInfo info;
+  if (!m_tid.LookupAttributeByName (name, &info))
+    {
+      return false;
+    }
+  if (!(info.flags & TypeId::ATTR_GET))
+    {
+      return false;
+    }
+  Attribute v = info.initialValue.Copy ();
+  bool ok = info.accessor->Get (this, v);
+  if (ok)
+    {
+      value = v.SerializeToString (info.checker);
+    }
+  return ok;
+}
+
+Attribute
+Object::GetAttribute (std::string name) const
+{
+  struct TypeId::AttributeInfo info;
+  if (!m_tid.LookupAttributeByName (name, &info))
+    {
+      return Attribute ();
+    }
+  if (!(info.flags & TypeId::ATTR_GET))
+    {
+      return Attribute ();
+    }
+  Attribute value = info.initialValue.Copy ();
+  bool ok = info.accessor->Get (this, value);
+  if (!ok)
+    {
+      return Attribute ();
+    }
+  return value;
+}
+
+bool 
+Object::TraceSourceConnect (std::string name, const CallbackBase &cb)
+{
+  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
+  if (accessor == 0)
+    {
+      return false;
+    }
+  bool ok = accessor->Connect (this, cb);
+  return ok;
+}
+bool 
+Object::TraceSourceDisconnect (std::string name, const CallbackBase &cb)
+{
+  Ptr<const TraceSourceAccessor> accessor = m_tid.LookupTraceSourceByName (name);
+  if (accessor == 0)
+    {
+      return false;
+    }
+  bool ok = accessor->Disconnect (this, cb);
+  return ok;
+}
+
+TypeId 
+Object::GetRealTypeId (void) const
+{
+  return m_tid;
+}
+
+
 Ptr<Object>
 Object::DoGetObject (TypeId tid) const
 {
@@ -408,7 +1221,9 @@
     current = current->m_next;
   } while (current != this);
 }
-
+void
+Object::NotifyConstructionCompleted (void)
+{}
 void 
 Object::AggregateObject (Ptr<Object> o)
 {
@@ -619,10 +1434,10 @@
   static ns3::TypeId GetTypeId (void) {
     static ns3::TypeId tid = ns3::TypeId ("DerivedA")
       .SetParent (BaseA::GetTypeId ())
-      .AddConstructor<DerivedA,int> ();
+      .AddConstructor<DerivedA> ();
     return tid;
   }
-  DerivedA (int v)
+  DerivedA ()
   {}
   void DerivedGenerateTrace (int16_t v)
   { m_sourceDerived = v; }
@@ -671,13 +1486,10 @@
   static ns3::TypeId GetTypeId (void) {
     static ns3::TypeId tid = ns3::TypeId ("DerivedB")
       .SetParent (BaseB::GetTypeId ())
-      .AddConstructor<DerivedB,int> ()
-      .AddConstructor<DerivedB,int,int &> ();
+      .AddConstructor<DerivedB> ();
     return tid;
   }
-  DerivedB (int v)
-  {}
-  DerivedB (int v1, int &v2)
+  DerivedB ()
   {}
   void DerivedGenerateTrace (int16_t v)
   { m_sourceDerived = v; }
@@ -754,7 +1566,7 @@
   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
   NS_TEST_ASSERT_EQUAL (baseA->GetObject<DerivedA> (), 0);
-  baseA = CreateObject<DerivedA> (10);
+  baseA = CreateObject<DerivedA> ();
   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (), baseA);
   NS_TEST_ASSERT_EQUAL (baseA->GetObject<BaseA> (DerivedA::GetTypeId ()), baseA);
   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedA> (), 0);
@@ -773,8 +1585,8 @@
   NS_TEST_ASSERT_EQUAL (baseB->GetObject<DerivedA> (), 0);
   NS_TEST_ASSERT_UNEQUAL (baseBCopy->GetObject<BaseA> (), 0);
 
-  baseA = CreateObject<DerivedA> (1);
-  baseB = CreateObject<DerivedB> (1);
+  baseA = CreateObject<DerivedA> ();
+  baseB = CreateObject<DerivedB> ();
   baseBCopy = baseB;
   baseA->AggregateObject (baseB);
   NS_TEST_ASSERT_UNEQUAL (baseA->GetObject<DerivedB> (), 0);
@@ -836,7 +1648,7 @@
   baseA->TraceDisconnect ("/$BaseA/basea-x", MakeCallback (&ObjectTest::BaseATrace, this));
 
   Ptr<DerivedA> derivedA;
-  derivedA = CreateObject<DerivedA> (1);
+  derivedA = CreateObject<DerivedA> ();
   baseB = CreateObject<BaseB> ();
   derivedA->AggregateObject (baseB);
   baseB->TraceConnect ("/$DerivedA/deriveda-x", MakeCallback (&ObjectTest::DerivedATrace, this));
@@ -866,7 +1678,7 @@
   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), 0);
   NS_TEST_ASSERT_EQUAL (a->GetObject<DerivedA> (), 0);
-  a = DerivedA::GetTypeId ().CreateObject (10);
+  a = DerivedA::GetTypeId ().CreateObject ();
   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (), a);
   NS_TEST_ASSERT_EQUAL (a->GetObject<BaseA> (DerivedA::GetTypeId ()), a);
   NS_TEST_ASSERT_UNEQUAL (a->GetObject<DerivedA> (), 0);
--- a/src/core/object.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/object.h	Wed Feb 27 22:19:39 2008 +0100
@@ -26,13 +26,15 @@
 #include "ptr.h"
 #include "trace-resolver.h"
 #include "callback.h"
-#include "empty.h"
+#include "attribute.h"
+#include "object-base.h"
+#include "attribute-helper.h"
 
 #define NS_OBJECT_ENSURE_REGISTERED(type)       \
   static struct X##type##RegistrationClass      \
   {                                             \
     X##type##RegistrationClass () {             \
-      ns3::TypeId tid = type::GetTypeId ();      \
+      ns3::TypeId tid = type::GetTypeId ();     \
       tid.GetParent ();                         \
     }                                           \
 } x_##type##RegistrationVariable
@@ -43,14 +45,30 @@
 class TraceContext;
 class CallbackBase;
 class Object;
+class AttributeAccessor;
+class AttributeValue;
+class AttributeList;
+class TraceSourceAccessor;
 
 /**
  * \brief a unique identifier for an interface.
  *
+ * This class records a lot of meta-information about a 
+ * subclass of the Object base class:
+ *  - the base class of the subclass
+ *  - the set of accessible constructors in the subclass
+ *  - the set of 'attributes' accessible in the subclass
  */
 class TypeId
 {
 public:
+  enum {
+    ATTR_GET = 1<<0,
+    ATTR_SET = 1<<1,
+    ATTR_CONSTRUCT = 1<<2,
+    ATTR_SGC = ATTR_GET | ATTR_SET | ATTR_CONSTRUCT,
+  };
+
   /**
    * \param name the name of the requested interface
    * \returns the unique id associated with the requested
@@ -60,8 +78,24 @@
    * name is not a valid interface name.
    */
   static TypeId LookupByName (std::string name);
+
+  /**
+   * \returns the number of TypeId instances constructed
+   */
   static uint32_t GetRegisteredN (void);
+  /**
+   * \param i index
+   * \returns the TypeId instance whose index is \i.
+   */
   static TypeId GetRegistered (uint32_t i);
+
+  /**
+   * \param name the name of the interface to construct.
+   *
+   * No two instances can share the same name.
+   */
+  TypeId (const char * name);
+
   /**
    * \returns the parent of this TypeId
    *
@@ -74,6 +108,15 @@
   TypeId GetParent (void) const;
 
   /**
+   * \returns the name of the group associated to this TypeId.
+   */
+  std::string GetGroupName (void) const;
+  /**
+   * \returns the fully-qualified C++ typename of this TypeId.
+   */
+  std::string GetTypeName (void) const;
+
+  /**
    * \returns the name of this interface.
    */
   std::string GetName (void) const;
@@ -83,64 +126,280 @@
    */
   bool HasConstructor (void) const;
 
-  TypeId (std::string);
+  /**
+   * \returns the number of attributes associated to this TypeId
+   */
+  uint32_t GetAttributeListN (void) const;
+  /**
+   * \param i index into attribute array
+   * \returns the name associated to the attribute whose
+   *          index is \i i.
+   */
+  std::string GetAttributeName (uint32_t i) const;
+  /**
+   * \param i index into attribute array
+   * \returns the full name associated to the attribute whose
+   *          index is \i i.
+   */
+  std::string GetAttributeFullName (uint32_t i) const;
+
+  Attribute GetAttributeInitialValue (uint32_t i) const;
+
+  uint32_t GetTraceSourceN (void) const;
+  std::string GetTraceSourceName (uint32_t i) const;
+  std::string GetTraceSourceHelp (uint32_t i) const;
+  Ptr<const TraceSourceAccessor> GetTraceSourceAccessor (uint32_t i) const;
 
+  Ptr<Object> CreateObject (const AttributeList &attributes) const;
+
+
+  Ptr<Object> CreateObject (void) const;
+  template <typename T1>
+  Ptr<Object> CreateObject (T1 a1) const;
+  template <typename T1, typename T2>
+  Ptr<Object> CreateObject (T1 a1, T2 a2) const;
+
+
+  /**
+   * \param tid the TypeId of the base class.
+   * \return this TypeId instance.
+   *
+   * Record in this TypeId which TypeId is the TypeId
+   * of the base class of the subclass.
+   */
   TypeId SetParent (TypeId tid);
+  /**
+   * \return this TypeId instance.
+   *
+   * Record in this TypeId which TypeId is the TypeId
+   * of the base class of the subclass.
+   */
   template <typename T>
   TypeId SetParent (void);
 
+  /**
+   * \param groupName the name of the group this TypeId belongs to.
+   * \returns this TypeId instance.
+   *
+   * The group name is purely an advisory information used to 
+   * group together types according to a user-specific grouping
+   * scheme.
+   */
+  TypeId SetGroupName (std::string groupName);
+  
+  /**
+   * \param typeName the fully-qualified C++ typename of this TypeId.
+   * \returns this TypeId instance.
+   */
+  TypeId SetTypeName (std::string typeName);
+
+  /**
+   * \returns this TypeId instance
+   *
+   * Record in this TypeId the fact that the default constructor
+   * is accessible.
+   */
   template <typename T>
   TypeId AddConstructor (void);
+
   template <typename T, typename T1>
   TypeId AddConstructor (void);
+
   template <typename T, typename T1, typename T2>
   TypeId AddConstructor (void);
-  template <typename T, typename T1, typename T2, typename T3>
-  TypeId AddConstructor (void);
-  template <typename T, typename T1, typename T2, typename T3, typename T4>
-  TypeId AddConstructor (void);
-  template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-  TypeId AddConstructor (void);
+
+  /**
+   * \param name the name of the new attribute
+   * \param help some help text which describes the purpose of this
+   *        attribute
+   * \param param an instance of the associated Accessor subclass
+   * \returns this TypeId instance
+   *
+   * Record in this TypeId the fact that a new attribute exists.
+   */
+  TypeId AddAttribute (std::string name,
+                       std::string help, 
+                       Attribute initialValue,
+                       Ptr<const AttributeAccessor> spec,
+                       Ptr<const AttributeChecker> checker);
+
+  /**
+   * \param name the name of the new attribute
+   * \param help some help text which describes the purpose of this
+   *        attribute
+   * \param flags flags which describe how this attribute can be read and/or written.
+   * \param param an instance of the associated Accessor subclass
+   * \returns this TypeId instance
+   *
+   * Record in this TypeId the fact that a new attribute exists.
+   */
+  TypeId AddAttribute (std::string name,
+                       std::string help, 
+                       uint32_t flags,
+                       Attribute initialValue,
+                       Ptr<const AttributeAccessor> accessor,
+                       Ptr<const AttributeChecker> checker);
+
+  TypeId AddTraceSource (std::string name,
+                         std::string help,
+                         Ptr<const TraceSourceAccessor> accessor);
+
+  struct AttributeInfo {
+    Ptr<const AttributeAccessor> accessor;
+    Attribute initialValue;
+    uint32_t flags;
+    Ptr<const AttributeChecker> checker;
+  };
+  /**
+   * \param name the name of the requested attribute
+   */
+  bool LookupAttributeByName (std::string name, struct AttributeInfo *info) const;
 
 
-  Ptr<Object> CreateObject (void);
-  template <typename T1>
-  Ptr<Object> CreateObject (T1 a1);
-  template <typename T1, typename T2>
-  Ptr<Object> CreateObject (T1 a1, T2 a2);
-  template <typename T1, typename T2, typename T3>
-  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3);
-  template <typename T1, typename T2, typename T3, typename T4>
-  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-  Ptr<Object> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
+  // construct an invalid TypeId.
+  TypeId ();
+  ~TypeId ();
 
-  ~TypeId ();
+  VALUE_HELPER_HEADER_1 (TypeId);
 private:
+  friend class Object;
+  friend class AttributeList;
   friend bool operator == (TypeId a, TypeId b);
   friend bool operator != (TypeId a, TypeId b);
 
+
+  Ptr<const TraceSourceAccessor> LookupTraceSourceByName (std::string name) const;
+
+  /**
+   * \param i the position of the requested attribute
+   * \returns the Accessor associated to the requested attribute
+   */
+  bool LookupAttributeByPosition (uint32_t i, struct AttributeInfo *info) const;
+  /**
+   * \param fullName the full name of the requested attribute
+   * \returns the Accessor associated to the requested attribute
+   */
+  static bool LookupAttributeByFullName (std::string fullName, struct AttributeInfo *info);
+
   explicit TypeId (uint16_t tid);
   void DoAddConstructor (CallbackBase callback, uint32_t nArguments);
-  CallbackBase LookupConstructor (uint32_t nArguments);
+  CallbackBase LookupConstructor (uint32_t nArguments) const;
+  Ptr<const AttributeAccessor> GetAttributeAccessor (uint32_t i) const;
+  uint32_t GetAttributeFlags (uint32_t i) const;
+  Ptr<const AttributeChecker> GetAttributeChecker (uint32_t i) const;
   
   uint16_t m_tid;
 };
 
+std::ostream & operator << (std::ostream &os, TypeId tid);
+std::istream & operator >> (std::istream &is, TypeId &tid);
+
+VALUE_HELPER_HEADER_2 (TypeId);
+
+/**
+ * \brief a container of attributes to be used during object's construction
+ *        and in ns3::Object::Set.
+ *
+ */
+class AttributeList
+{
+public:
+  AttributeList ();
+  AttributeList (const AttributeList &o);
+  AttributeList &operator = (const AttributeList &o);
+  ~AttributeList ();
+  /**
+   * \param name the name of the attribute to set
+   * \param value the value to set
+   *
+   * This method checks that a attribute with the requested
+   * name exists and that the value specified is an acceptable
+   * value of that attribute. If any of these checks fails,
+   * the program terminates with a message.
+   */
+  bool Set (std::string name, Attribute value);
+
+  void SetWithTid (TypeId tid, std::string name, Attribute value);
+  void SetWithTid (TypeId tid, uint32_t position, Attribute value);
+
+  /**
+   * Clear the content of this instance.
+   */
+  void Reset (void);
+
+  /**
+   * \returns the global attribute container
+   *
+   * The global attribute container can be used to specify
+   * a set of attribute values without having to re-specify
+   * them for each object when it is created. This container
+   * is checked only during object construction and 
+   * it is always checked last, after any per-object
+   * container is checked.
+   */
+  static AttributeList *GetGlobal (void);
+
+  std::string SerializeToString (void) const;
+  bool DeserializeFromString (std::string value);
+private:
+  friend class Object;
+  struct Attr {
+    Ptr<const AttributeChecker> checker;
+    Attribute value;
+  };
+  typedef std::vector<struct Attr> Attrs;
+  typedef Attrs::iterator Iterator;
+  typedef Attrs::const_iterator CIterator;
+
+
+
+  bool DoSet (struct TypeId::AttributeInfo *info, Attribute param);
+  void DoSetOne (Ptr<const AttributeChecker> checker, Attribute param);
+  std::string LookupAttributeFullNameByChecker (Ptr<const AttributeChecker> checker) const;
+
+  Attrs m_attributes;
+};
+
+
 /**
  * \brief a base class which provides memory management and object aggregation
  *
- * Note: This base class is quite similar in spirit to IUnknown in COM or
- * BonoboObject in Bonobo: it provides three main methods: Ref, Unref and
- * GetObject.
  */
-class Object
+class Object : public ObjectBase
 {
 public:
   static TypeId GetTypeId (void);
 
   Object ();
   virtual ~Object ();
+
+  /**
+   * \param name the name of the attribute to set
+   * \param value the name of the attribute to set
+   *
+   * Set a single attribute.
+   */
+  bool SetAttribute (std::string name, Attribute value);
+  /**
+   * \param name the name of the attribute to read
+   * \param value a reference to the string where the value of the 
+   *        attribute should be stored.
+   * \returns true if the requested attribute was found, false otherwise.
+   */
+  bool GetAttribute (std::string name, std::string &value) const;
+  /**
+   * \param name the name of the attribute to read
+   * \param value a reference to the object where the value of the 
+   *        attribute should be stored.
+   * \returns true if the requested attribute was found, false otherwise.
+   */
+  Attribute GetAttribute (std::string name) const;
+
+  bool TraceSourceConnect (std::string name, const CallbackBase &cb);
+  bool TraceSourceDisconnect (std::string name, const CallbackBase &cb);
+
+  TypeId GetRealTypeId (void) const;
+
   /**
    * Increment the reference count. This method should not be called
    * by user code. Object instances are expected to be used in conjunction
@@ -214,8 +473,13 @@
    * up to their parent's implementation once they are done.
    */
   virtual void DoDispose (void);
+  virtual void NotifyConstructionCompleted (void);
 private:
   friend class TypeIdTraceResolver;
+
+  template <typename T>
+  friend Ptr<T> CreateObject (const AttributeList &attributes);
+
   template <typename T>
   friend Ptr<T> CreateObject (void);
   template <typename T, typename T1>
@@ -233,57 +497,76 @@
   template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
   friend Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
 
+
+  bool DoSet (Ptr<const AttributeAccessor> spec, Attribute intialValue, 
+              Ptr<const AttributeChecker> checker, Attribute value);
   Ptr<Object> DoGetObject (TypeId tid) const;
   void DoCollectSources (std::string path, const TraceContext &context, 
                          TraceResolver::SourceCollection *collection) const;
   void DoTraceAll (std::ostream &os, const TraceContext &context) const;
   bool Check (void) const;
   bool CheckLoose (void) const;
+  /**
+   * Attempt to delete this object. This method iterates
+   * over all aggregated objects to check if they all 
+   * have a zero refcount. If yes, the object and all
+   * its aggregates are deleted. If not, nothing is done.
+   */
   void MaybeDelete (void) const;
   /**
    * \param tid an TypeId
    *
-   * Every subclass which defines a new TypeId for itself
-   * should register this TypeId by calling this method
-   * from its constructor.
+   * Invoked from ns3::CreateObject only.
+   * Initialize the m_tid member variable to
+   * keep track of the type of this object instance.
    */
   void SetTypeId (TypeId tid);
+  /**
+   * \param attributes the attribute values used to initialize 
+   *        the member variables of this object's instance.
+   *
+   * Invoked from ns3::CreateObject only.
+   * Initialize all the member variables which were
+   * registered with the associated TypeId.
+   */
+  void Construct (const AttributeList &attributes);
 
+  /**
+   * The reference count for this object. Each aggregate
+   * has an individual reference count. When the global
+   * reference count (the sum of all reference counts) 
+   * reaches zero, the object and all its aggregates is 
+   * deleted.
+   */
   mutable uint32_t m_count;
+  /**
+   * Identifies the type of this object instance.
+   */
   TypeId m_tid;
+  /**
+   * Set to true when the DoDispose method of the object
+   * has run, false otherwise.
+   */
   bool m_disposed;
   mutable bool m_collecting;
+  /**
+   * A pointer to the next aggregate object. This is a circular
+   * linked list of aggregated objects: the last one points
+   * back to the first one. If an object is not aggregated to
+   * any other object, the value of this field is equal to the
+   * value of the 'this' pointer.
+   */
   Object *m_next;
 };
 
-template <typename T>
-Ptr<T> CreateObject (void);
-
-template <typename T, typename T1>
-Ptr<T> CreateObject (T1 a1);
-
-template <typename T, typename T1, typename T2>
-Ptr<T> CreateObject (T1 a1, T2 a2);
-
-template <typename T, typename T1, typename T2, typename T3>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6);
-
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
-Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7);
-
 } // namespace ns3
 
 namespace ns3 {
 
+/*************************************************************************
+ *   The TypeId implementation which depends on templates
+ *************************************************************************/
+
 template <typename T>
 TypeId 
 TypeId::SetParent (void)
@@ -296,8 +579,8 @@
 TypeId::AddConstructor (void)
 {
   struct Maker {
-    static Ptr<Object> Create (void) {
-      return ns3::CreateObject<T> ();
+    static Ptr<Object> Create (const AttributeList &attributes) {
+      return ns3::CreateObject<T> (attributes);
     }
   };
   CallbackBase cb = MakeCallback (&Maker::Create);
@@ -330,49 +613,9 @@
   DoAddConstructor (cb, 2);
   return *this;
 }
-template <typename T, typename T1, typename T2, typename T3>
-TypeId 
-TypeId::AddConstructor (void)
-{
-  struct Maker {
-    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3) {
-      return ns3::CreateObject<T,T1,T2,T3> (a1, a2, a3);
-    }
-  };
-  CallbackBase cb = MakeCallback (&Maker::Create);
-  DoAddConstructor (cb, 3);
-  return *this;
-}
-template <typename T, typename T1, typename T2, typename T3, typename T4>
-TypeId 
-TypeId::AddConstructor (void)
-{
-  struct Maker {
-    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4) {
-      return ns3::CreateObject<T,T1,T2,T3,T4> (a1, a2, a3, a4);
-    }
-  };
-  CallbackBase cb = MakeCallback (&Maker::Create);
-  DoAddConstructor (cb, 4);
-  return *this;
-}
-template <typename T, typename T1, typename T2, typename T3, typename T4, typename T5>
-TypeId 
-TypeId::AddConstructor (void)
-{
-  struct Maker {
-    static Ptr<Object> Create (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
-      return ns3::CreateObject<T,T1,T2,T3,T4,T5> (a1, a2, a3, a4, a5);
-    }
-  };
-  CallbackBase cb = MakeCallback (&Maker::Create);
-  DoAddConstructor (cb, 5);
-  return *this;
-}
-
 template <typename T1>
 Ptr<Object> 
-TypeId::CreateObject (T1 a1)
+TypeId::CreateObject (T1 a1) const
 {
   CallbackBase cb = LookupConstructor (1);
   Callback<Ptr<Object>,T1> realCb;
@@ -382,7 +625,7 @@
 }
 template <typename T1, typename T2>
 Ptr<Object> 
-TypeId::CreateObject (T1 a1, T2 a2)
+TypeId::CreateObject (T1 a1, T2 a2) const
 {
   CallbackBase cb = LookupConstructor (2);
   Callback<Ptr<Object>,T1,T2> realCb;
@@ -390,38 +633,10 @@
   Ptr<Object> object = realCb (a1,a2);
   return object;
 }
-template <typename T1, typename T2, typename T3>
-Ptr<Object> 
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3)
-{
-  CallbackBase cb = LookupConstructor (3);
-  Callback<Ptr<Object>,T1,T2,T3> realCb;
-  realCb.Assign (cb);
-  Ptr<Object> object = realCb (a1,a2,a3);
-  return object;
-}
-template <typename T1, typename T2, typename T3, typename T4>
-Ptr<Object> 
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4)
-{
-  CallbackBase cb = LookupConstructor (4);
-  Callback<Ptr<Object>,T1,T2,T3,T4> realCb;
-  realCb.Assign (cb);
-  Ptr<Object> object = realCb (a1,a2,a3,a4);
-  return object;
-}
-  template <typename T1, typename T2, typename T3, typename T4, typename T5>
-Ptr<Object> 
-TypeId::CreateObject (T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
-{
-  CallbackBase cb = LookupConstructor (5);
-  Callback<Ptr<Object>,T1,T2,T3,T4,T5> realCb;
-  realCb.Assign (cb);
-  Ptr<Object> object = realCb (a1,a2,a3,a4,a5);
-  return object;
-}
 
-
+/*************************************************************************
+ *   The Object implementation which depends on templates
+ *************************************************************************/
 
 void
 Object::Ref (void) const
@@ -463,11 +678,26 @@
   return 0;
 }
 
+/*************************************************************************
+ *   The helper functions which need templates.
+ *************************************************************************/
+
+
+template <typename T>
+Ptr<T> CreateObject (const AttributeList &attributes)
+{
+  Ptr<T> p = Ptr<T> (new T (), false);
+  p->SetTypeId (T::GetTypeId ());
+  p->Object::Construct (attributes);
+  return p;  
+}
+
 template <typename T>
 Ptr<T> CreateObject (void)
 {
   Ptr<T> p = Ptr<T> (new T (), false);
   p->SetTypeId (T::GetTypeId ());
+  p->Object::Construct (AttributeList ());
   return p;
 }
 
@@ -476,6 +706,7 @@
 {
   Ptr<T> p = Ptr<T> (new T (a1), false);
   p->SetTypeId (T::GetTypeId ());
+  p->Object::Construct (AttributeList ());
   return p;
 }
 
@@ -484,9 +715,9 @@
 {
   Ptr<T> p = Ptr<T> (new T (a1, a2), false);
   p->SetTypeId (T::GetTypeId ());
+  p->Object::Construct (AttributeList ());
   return p;
 }
-
 template <typename T, typename T1, typename T2, typename T3>
 Ptr<T> CreateObject (T1 a1, T2 a2, T3 a3)
 {
@@ -528,6 +759,32 @@
 }
 
 
+template <typename T>
+Ptr<T> 
+CreateObjectWith (std::string n1 = "", Attribute v1 = Attribute (),
+                  std::string n2 = "", Attribute v2 = Attribute (),
+                  std::string n3 = "", Attribute v3 = Attribute (),
+                  std::string n4 = "", Attribute v4 = Attribute (),
+                  std::string n5 = "", Attribute v5 = Attribute (),
+                  std::string n6 = "", Attribute v6 = Attribute (),
+                  std::string n7 = "", Attribute v7 = Attribute (),
+                  std::string n8 = "", Attribute v8 = Attribute (),
+                  std::string n9 = "", Attribute v9 = Attribute ())
+              
+{
+  AttributeList attributes;
+  attributes.SetWithTid (T::GetTypeId (), n1, v1);
+  attributes.SetWithTid (T::GetTypeId (), n2, v2);
+  attributes.SetWithTid (T::GetTypeId (), n3, v3);
+  attributes.SetWithTid (T::GetTypeId (), n4, v4);
+  attributes.SetWithTid (T::GetTypeId (), n5, v5);
+  attributes.SetWithTid (T::GetTypeId (), n6, v6);
+  attributes.SetWithTid (T::GetTypeId (), n7, v7);
+  attributes.SetWithTid (T::GetTypeId (), n8, v8);
+  attributes.SetWithTid (T::GetTypeId (), n9, v9);
+  return CreateObject<T> (attributes);
+}
+
 } // namespace ns3
 
 #endif /* OBJECT_H */
--- a/src/core/ptr.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/ptr.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,6 +23,7 @@
 #ifdef RUN_SELF_TESTS
 
 #include "test.h"
+#include "object-base.h"
 
 namespace ns3 {
 
@@ -45,7 +46,7 @@
 };
 
 
-class Base
+class Base : public ObjectBase
 {
 public:
   Base ();
@@ -286,7 +287,6 @@
     delete raw;
   }
 
-
   m_nDestroyed = 0;
   {
     Ptr<NoCount> p = Create<NoCount> (this);
@@ -317,12 +317,12 @@
   }
 #if 0
   {
-    Ptr<NoCount> p = CreateObject<NoCount> (cb);
+    Ptr<NoCount> p = Create<NoCount> (cb);
     Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
     callback ();
   }
   {
-    Ptr<const NoCount> p = CreateObject<NoCount> (cb);
+    Ptr<const NoCount> p = Create<NoCount> (cb);
     Callback<void> callback = MakeCallback (&NoCount::Nothing, p);
     callback ();
   }
--- a/src/core/random-variable.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/random-variable.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -28,6 +28,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>       
+#include <sstream>
 
 
 #include "assert.h"
@@ -51,7 +52,7 @@
   RandomVariableBase (const RandomVariableBase &o);
   virtual ~RandomVariableBase();
   virtual double  GetValue() = 0;
-  virtual uint32_t GetIntValue();
+  virtual uint32_t GetInteger();
   virtual RandomVariableBase*   Copy(void) const = 0;
   virtual void GetSeed(uint32_t seed[6]);
 
@@ -126,7 +127,7 @@
   delete m_generator;
 }
 
-uint32_t RandomVariableBase::GetIntValue() 
+uint32_t RandomVariableBase::GetInteger() 
 {
   return (uint32_t)GetValue();
 }
@@ -249,6 +250,10 @@
 RandomVariable &
 RandomVariable::operator = (const RandomVariable &o)
 {
+  if (&o == this)
+    {
+      return *this;
+    }
   delete m_variable;
   m_variable = o.m_variable->Copy ();
   return *this;
@@ -264,9 +269,9 @@
 }
 
 uint32_t 
-RandomVariable::GetIntValue (void) const
+RandomVariable::GetInteger (void) const
 {
-  return m_variable->GetIntValue ();
+  return m_variable->GetInteger ();
 }
 void 
 RandomVariable::GetSeed(uint32_t seed[6]) const
@@ -290,11 +295,27 @@
   RandomVariableBase::SetRunNumber (n);
 }
 RandomVariableBase *
-RandomVariable::Peek (void)
+RandomVariable::Peek (void) const
 {
   return m_variable;
 }
+RandomVariable::RandomVariable (Attribute value)
+  : m_variable (0)
+{
+  const RandomVariableValue *v = value.DynCast<const RandomVariableValue *> ();
+  if (v == 0)
+    {
+      NS_FATAL_ERROR ("Unexpected type of value. Expected \"RandomVariableValue\"");
+    }
+  *this = v->Get ();
+}
+RandomVariable::operator Attribute () const
+{
+  return Attribute::Create<RandomVariableValue> (*this);
+}
 
+ATTRIBUTE_VALUE_IMPLEMENT (RandomVariable);
+ATTRIBUTE_CHECKER_IMPLEMENT (RandomVariable);
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -316,6 +337,9 @@
   UniformVariableImpl(double s, double l);
 
   UniformVariableImpl(const UniformVariableImpl& c);
+
+  double GetMin (void) const;
+  double GetMax (void) const;
   
   /**
    * \return A value between low and high values specified by the constructor
@@ -344,6 +368,18 @@
 UniformVariableImpl::UniformVariableImpl(const UniformVariableImpl& c) 
   : RandomVariableBase(c), m_min(c.m_min), m_max(c.m_max) { }
 
+double 
+UniformVariableImpl::GetMin (void) const
+{
+  return m_min;
+}
+double 
+UniformVariableImpl::GetMax (void) const
+{
+  return m_max;
+}
+
+
 double UniformVariableImpl::GetValue()
 {
   if(!RandomVariableBase::initialized)
@@ -420,7 +456,7 @@
    * \return The constant value specified
    */
   virtual double  GetValue();
-  virtual uint32_t GetIntValue();
+  virtual uint32_t GetInteger();
   virtual RandomVariableBase*   Copy(void) const;
 private:
   double m_const;
@@ -443,7 +479,7 @@
   return m_const;
 }
 
-uint32_t ConstantVariableImpl::GetIntValue()
+uint32_t ConstantVariableImpl::GetInteger()
 {
   return (uint32_t)m_const;
 }
@@ -1241,7 +1277,7 @@
   /**
    * \return An integer value from this empirical distribution
    */
-  virtual uint32_t GetIntValue();
+  virtual uint32_t GetInteger();
 private:
   virtual double Interpolate(double, double, double, double, double);
 };
@@ -1249,7 +1285,7 @@
 
 IntEmpiricalVariableImpl::IntEmpiricalVariableImpl() { }
 
-uint32_t IntEmpiricalVariableImpl::GetIntValue()
+uint32_t IntEmpiricalVariableImpl::GetInteger()
 {
   return (uint32_t)GetValue();
 }
@@ -1563,6 +1599,55 @@
 }
 
 
+std::ostream &operator << (std::ostream &os, const RandomVariable &var)
+{
+  RandomVariableBase *base = var.Peek ();
+  ConstantVariableImpl *constant = dynamic_cast<ConstantVariableImpl *> (base);
+  if (constant != 0)
+    {
+      os << "Constant:" << constant->GetValue ();
+      return os;
+    }
+  UniformVariableImpl *uniform = dynamic_cast<UniformVariableImpl *> (base);
+  if (uniform != 0)
+    {
+      os << "Uniform:" << uniform->GetMin () << ":" << uniform->GetMax ();
+      return os;
+    }
+  // XXX: support other distributions
+  os.setstate (std::ios_base::badbit);
+  return os;
+}
+std::istream &operator >> (std::istream &is, RandomVariable &var)
+{
+  std::string value;
+  is >> value;
+  std::string::size_type tmp;
+  tmp = value.find (":");
+  if (tmp == std::string::npos)
+    {
+      is.setstate (std::ios_base::badbit);
+      return is;
+    }
+  std::string type = value.substr (0, tmp);
+  if (value == "Constant")
+    {
+      // XXX parse
+      var = ConstantVariable ();
+    }
+  else if (value == "Uniform")
+    {
+      // XXX parse
+      var = UniformVariable ();
+    }
+  else
+    {
+      // XXX: support other distributions.
+    }
+  return is;
+}
+
+
 
 }//namespace ns3
 
--- a/src/core/random-variable.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/random-variable.h	Wed Feb 27 22:19:39 2008 +0100
@@ -24,6 +24,10 @@
 #include <vector>
 #include <algorithm>
 #include <stdint.h>
+#include <istream>
+#include <ostream>
+#include "attribute.h"
+#include "attribute-helper.h"
 
 /**
  * \ingroup core
@@ -68,7 +72,7 @@
    * \brief Returns a random integer integer from the underlying distribution
    * \return  Integer cast of ::GetValue()
    */
-  uint32_t GetIntValue (void) const;
+  uint32_t GetInteger (void) const;
   
   /**
    * \brief Get the internal state of the RNG
@@ -158,11 +162,19 @@
    * \endcode
    */
   static void SetRunNumber(uint32_t n);
+
+
+  RandomVariable (Attribute value);
+  operator Attribute () const;
+
 private:
+  friend std::ostream &operator << (std::ostream &os, const RandomVariable &var);
+  friend std::istream &operator >> (std::istream &os, RandomVariable &var);
+
   RandomVariableBase *m_variable;
 protected:
   RandomVariable (const RandomVariableBase &variable);
-  RandomVariableBase *Peek (void);
+  RandomVariableBase *Peek (void) const;
 };
 
 /**
@@ -648,5 +660,14 @@
   static double GetSingleValue(double s, double l, double mean);
 };
 
+std::ostream &operator << (std::ostream &os, const RandomVariable &var);
+std::istream &operator >> (std::istream &os, RandomVariable &var);
+
+ATTRIBUTE_VALUE_DEFINE (RandomVariable);
+ATTRIBUTE_CHECKER_DEFINE (RandomVariable);
+ATTRIBUTE_ACCESSOR_DEFINE (RandomVariable);
+
 }//namespace ns3
+
+
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/string.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,45 @@
+#include "string.h"
+
+namespace ns3 {
+
+String::String ()
+  : m_value ()
+{}
+String::String (const char *value)
+  : m_value (value)
+{}
+String::String (std::string value)
+  : m_value (value)
+{}
+void 
+String::Set (std::string value)
+{
+  m_value = value;
+}
+void 
+String::Set (const char *value)
+{
+  m_value = value;
+}
+std::string 
+String::Get (void) const
+{
+  return m_value;
+}
+
+std::ostream & operator << (std::ostream &os, const String &value)
+{
+  os << value.Get ();
+  return os;
+}
+std::istream &operator >> (std::istream &is, String &value)
+{
+  std::string str;
+  is >> str;
+  value = String (str);
+  return is;
+}
+
+VALUE_HELPER_CPP (String);
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/string.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,32 @@
+#ifndef NS3_STRING_H
+#define NS3_STRING_H
+
+#include <string>
+#include "attribute-helper.h"
+
+namespace ns3 {
+
+class String
+{
+public:
+  String ();
+  String (const char *value);
+  String (std::string value);
+  void Set (std::string value);
+  void Set (const char *value);
+  std::string Get (void) const;
+
+  VALUE_HELPER_HEADER_1 (String);
+private:
+  std::string m_value;
+};
+
+std::ostream & operator << (std::ostream &os, const String &value);
+std::istream &operator >> (std::istream &is, String &value);
+
+VALUE_HELPER_HEADER_2 (String);
+
+} // namespace ns3
+
+
+#endif /* NS3_STRING_H */
--- a/src/core/trace-resolver.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/trace-resolver.h	Wed Feb 27 22:19:39 2008 +0100
@@ -25,6 +25,7 @@
 #include <list>
 #include "trace-context.h"
 #include "trace-doc.h"
+#include "object-base.h"
 
 namespace ns3 {
 
@@ -39,7 +40,7 @@
  * subclasses, doing so is complicated so, it is recommended to use
  * the default implementation ns3::CompositeTraceResolver instead.
  */
-class TraceResolver
+class TraceResolver : public ObjectBase
 {
 public:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/trace-source-accessor.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,25 @@
+#include "trace-source-accessor.h"
+
+namespace ns3 {
+
+TraceSourceAccessor::TraceSourceAccessor ()
+  : m_count (1)
+{}
+TraceSourceAccessor::~TraceSourceAccessor ()
+{}
+void 
+TraceSourceAccessor::Ref (void) const
+{
+  m_count++;
+}
+void 
+TraceSourceAccessor::Unref (void) const
+{
+  m_count--;
+  if (m_count == 0)
+    {
+      delete this;
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/trace-source-accessor.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,71 @@
+#ifndef TRACE_SOURCE_ACCESSOR_H
+#define TRACE_SOURCE_ACCESSOR_H
+
+#include <stdint.h>
+#include "object-base.h"
+#include "callback.h"
+#include "ptr.h"
+
+namespace ns3 {
+
+class TraceSourceAccessor : public ObjectBase
+{
+public:
+  TraceSourceAccessor ();
+  virtual ~TraceSourceAccessor ();
+  void Ref (void) const;
+  void Unref (void) const;
+
+  virtual bool Connect (ObjectBase *obj, const CallbackBase &cb) const = 0;
+  virtual bool Disconnect (ObjectBase *obj, const CallbackBase &cb) const = 0;
+private:
+  mutable uint32_t m_count;
+};
+
+template <typename T>
+Ptr<const TraceSourceAccessor> MakeTraceSourceAccessor (T a);
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T, typename SOURCE>
+Ptr<const TraceSourceAccessor> 
+DoMakeTraceSourceAccessor (SOURCE T::*a)
+{
+  struct Accessor : public TraceSourceAccessor
+  {
+    virtual bool Connect (ObjectBase *obj, const CallbackBase &cb) const {
+      T *p = dynamic_cast<T*> (obj);
+      if (p == 0)
+	{
+	  return false;
+	}
+      (p->*m_source).Connect (cb);
+      return true;
+    }
+    virtual bool Disconnect (ObjectBase *obj, const CallbackBase &cb) const {
+      T *p = dynamic_cast<T*> (obj);
+      if (p == 0)
+	{
+	  return false;
+	}
+      (p->*m_source).Disconnect (cb);
+      return true;      
+    }
+    SOURCE T::*m_source;
+  } *accessor = new Accessor ();
+  accessor->m_source = a;
+  return Ptr<const TraceSourceAccessor> (accessor, false);
+}
+
+template <typename T>
+Ptr<const TraceSourceAccessor> MakeTraceSourceAccessor (T a)
+{
+  return DoMakeTraceSourceAccessor (a);
+}
+
+} // namespace ns3
+
+
+#endif /* TRACE_SOURCE_ACCESSOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/traced-callback.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,100 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "traced-callback.h"
+
+#ifdef RUN_SELF_TESTS
+
+#include "test.h"
+
+namespace ns3 {
+
+class TracedCallbackTest : public Test 
+{
+public:
+  TracedCallbackTest ();
+  virtual ~TracedCallbackTest ();
+  virtual bool RunTests (void);
+private:
+  void CbOne (uint8_t a, double b);
+  void CbTwo (uint8_t a, double b);
+
+  bool m_one;
+  bool m_two;
+};
+
+TracedCallbackTest::TracedCallbackTest ()
+  : Test ("TracedCallback")
+{}
+TracedCallbackTest::~TracedCallbackTest ()
+{}
+void
+TracedCallbackTest::CbOne (uint8_t a, double b)
+{
+  m_one = true;
+}
+void
+TracedCallbackTest::CbTwo (uint8_t a, double b)
+{
+  m_two = true;
+}
+bool 
+TracedCallbackTest::RunTests (void)
+{
+  bool result = true;
+
+  TracedCallback<uint8_t,double> trace;
+  trace.Connect (MakeCallback (&TracedCallbackTest::CbOne, this));
+  trace.Connect (MakeCallback (&TracedCallbackTest::CbTwo, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  NS_TEST_ASSERT (m_one);
+  NS_TEST_ASSERT (m_two);
+
+  trace.Disconnect (MakeCallback (&TracedCallbackTest::CbOne, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  NS_TEST_ASSERT (!m_one);
+  NS_TEST_ASSERT (m_two);
+  trace.Disconnect (MakeCallback (&TracedCallbackTest::CbTwo, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  NS_TEST_ASSERT (!m_one);
+  NS_TEST_ASSERT (!m_two);
+
+  trace.Connect (MakeCallback (&TracedCallbackTest::CbOne, this));
+  trace.Connect (MakeCallback (&TracedCallbackTest::CbTwo, this));
+  m_one = false;
+  m_two = false;
+  trace (1, 2);
+  NS_TEST_ASSERT (m_one);
+  NS_TEST_ASSERT (m_two);
+
+  return result;
+}
+
+static TracedCallbackTest g_eventTraceTest;
+
+}//namespace ns3
+
+#endif /* RUN_SELF_TESTS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/traced-callback.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,153 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#ifndef TRACED_CALLBACK_H
+#define TRACED_CALLBACK_H
+
+#include <list>
+#include "callback.h"
+
+namespace ns3 {
+
+/**
+ * \brief log arbitrary number of parameters to a matching ns3::Callback
+ * \ingroup tracing
+ *
+ * Whenever operator () is invoked on this class, the call and its arguments
+ * are forwarded to the internal matching ns3::Callback.
+ */
+template<typename T1 = empty, typename T2 = empty, 
+         typename T3 = empty, typename T4 = empty>
+class TracedCallback 
+{
+public:
+  TracedCallback ();
+  void Connect (const CallbackBase & callback);
+  void Disconnect (const CallbackBase & callback);
+  void operator() (void) const;
+  void operator() (T1 a1) const;
+  void operator() (T1 a1, T2 a2) const;
+  void operator() (T1 a1, T2 a2, T3 a3) const;
+  void operator() (T1 a1, T2 a2, T3 a3, T4 a4) const;
+
+private:
+  typedef std::list<Callback<void,T1,T2,T3,T4> > CallbackList;
+  CallbackList m_callbackList;
+};
+
+} // namespace ns3
+
+// implementation below.
+
+namespace ns3 {
+
+
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+TracedCallback<T1,T2,T3,T4>::TracedCallback ()
+  : m_callbackList () 
+{}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::Connect (const CallbackBase & callback)
+{
+  Callback<void,T1,T2,T3,T4> cb;
+  cb.Assign (callback);
+  m_callbackList.push_back (cb);
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::Disconnect (const CallbackBase & callback)
+{
+  for (typename CallbackList::iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); /* empty */)
+    {
+      if ((*i).IsEqual (callback))
+	{
+	  i = m_callbackList.erase (i);
+	}
+      else
+	{
+	  i++;
+	}
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::operator() (void) const
+{
+  for (typename CallbackList::const_iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) ();
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::operator() (T1 a1) const
+{
+  for (typename CallbackList::const_iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (a1);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::operator() (T1 a1, T2 a2) const
+{
+  for (typename CallbackList::const_iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (a1, a2);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3) const
+{
+  for (typename CallbackList::const_iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (a1, a2, a3);
+    }
+}
+template<typename T1, typename T2, 
+         typename T3, typename T4>
+void 
+TracedCallback<T1,T2,T3,T4>::operator() (T1 a1, T2 a2, T3 a3, T4 a4) const
+{
+  for (typename CallbackList::const_iterator i = m_callbackList.begin ();
+       i != m_callbackList.end (); i++)
+    {
+      (*i) (a1, a2, a3, a4);
+    }
+}
+
+}//namespace ns3
+
+#endif /* TRACED_CALLBACK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/traced-value.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,480 @@
+#ifndef TRACED_VALUE_H
+#define TRACED_VALUE_H
+
+#include "traced-callback.h"
+#include "integer.h"
+#include "uinteger.h"
+#include "boolean.h"
+#include "double.h"
+#include "enum.h"
+
+#define TRACE(x)
+
+namespace ns3 {
+
+template <typename T>
+class TracedValue
+{
+public:
+  TracedValue ()
+    : m_v () {}
+  TracedValue (const TracedValue &o)
+    : m_v (o.m_v) {}
+  TracedValue (const T &v)
+    : m_v (v) {}
+  operator T () const {
+    return m_v;
+  }
+  TracedValue &operator = (const TracedValue &o) {
+    TRACE ("x=");
+    Set (o.m_v);
+    return *this;
+  }
+  TracedValue (const Integer &value) 
+    : m_v (value.Get ()) {}
+  operator Integer () const {
+    return Integer (m_v);
+  }
+  TracedValue (const Uinteger &value)
+    : m_v (value.Get ()) {}
+  operator Uinteger () const {
+    return Uinteger (m_v);
+  }
+  TracedValue (const Boolean &value)
+    : m_v (value.Get ()) {}
+  operator Boolean () const {
+    return Boolean (m_v);
+  }
+  TracedValue (const Enum &value)
+    : m_v (value.Get ()) {}
+  operator Enum () const {
+    return Enum (m_v);
+  }
+  void Connect (const CallbackBase &cb) {
+    m_cb.Connect (cb);
+  }
+  void Disconnect (const CallbackBase &cb) {
+    m_cb.Disconnect (cb);
+  }
+  void Set (const T &v) {
+    if (m_v != v)
+      {
+	m_cb (m_v, v);
+	m_v = v;
+      }
+  }
+  T Get (void) const {
+    return m_v;
+  }
+  TracedValue &operator++ () {
+    TRACE ("++x");
+    T tmp = Get ();
+    ++tmp;
+    Set (tmp);
+    return *this;
+  }
+  TracedValue &operator-- () {
+    TRACE ("--x");
+    T tmp = Get ();
+    --tmp;
+    Set (tmp);
+    return *this;
+  }
+  TracedValue operator++ (int) {
+    TRACE ("x++");
+    TracedValue old (*this);
+    T tmp = Get ();
+    tmp++;
+    Set (tmp);
+    return old;
+  }
+  TracedValue operator-- (int) {
+    TRACE ("x--");
+    TracedValue old (*this);
+    T tmp = Get ();
+    tmp--;
+    Set (tmp);
+    return old;
+  }
+private:
+  T m_v;
+  TracedCallback<T,T> m_cb;
+};
+
+template <typename T, typename U>
+bool operator == (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x==x");
+  return lhs.Get () == rhs.Get ();
+}
+template <typename T, typename U>
+bool operator == (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x==");
+  return lhs.Get () == rhs;
+}
+template <typename T, typename U>
+bool operator == (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE ("==x");
+  return lhs == rhs.Get ();
+}
+
+template <typename T, typename U>
+bool operator != (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x!=x");
+  return lhs.Get () != rhs.Get ();
+}
+template <typename T, typename U>
+bool operator != (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x!=");
+  return lhs.Get () != rhs;
+}
+template <typename T, typename U>
+bool operator != (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE ("!=x");
+  return lhs != rhs.Get ();
+}
+
+template <typename T, typename U>
+bool operator <= (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x<=x");
+  return lhs.Get () <= rhs.Get ();
+}
+template <typename T, typename U>
+bool operator <= (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x<=");
+  return lhs.Get () <= rhs;
+}
+template <typename T, typename U>
+bool operator <= (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE ("<=x");
+  return lhs <= rhs.Get ();
+}
+template <typename T, typename U>
+bool operator >= (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x>=x");
+  return lhs.Get () >= rhs.Get ();
+}
+template <typename T, typename U>
+bool operator >= (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x>=");
+  return lhs.Get () >= rhs;
+}
+template <typename T, typename U>
+bool operator >= (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE (">=x");
+  return lhs >= rhs.Get ();
+}
+
+template <typename T, typename U>
+bool operator < (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x<x");
+  return lhs.Get () < rhs.Get ();
+}
+template <typename T, typename U>
+bool operator < (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x<");
+  return lhs.Get () < rhs;
+}
+template <typename T, typename U>
+bool operator < (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE ("<x");
+  return lhs < rhs.Get ();
+}
+template <typename T, typename U>
+bool operator > (const TracedValue<T> &lhs, const TracedValue<U> &rhs)
+{
+  TRACE ("x>x");
+  return lhs.Get () > rhs.Get ();
+}
+template <typename T, typename U>
+bool operator > (const TracedValue<T> &lhs, const U &rhs)
+{
+  TRACE ("x>");
+  return lhs.Get () > rhs;
+}
+template <typename T, typename U>
+bool operator > (const U &lhs, const TracedValue<T> &rhs)
+{
+  TRACE (">x");
+  return lhs > rhs.Get ();
+}
+template <typename T, typename U>
+TracedValue<T> &operator += (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x+=");
+  T tmp = lhs.Get ();
+  tmp += rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator -= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x-=");
+  T tmp = lhs.Get ();
+  tmp -= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator *= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x*=");
+  T tmp = lhs.Get ();
+  tmp *= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator /= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x/=");
+  T tmp = lhs.Get ();
+  tmp /= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator %= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x%=");
+  T tmp = lhs.Get ();
+  tmp %= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator <<= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x<<=");
+  T tmp = lhs.Get ();
+  tmp <<= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator >>= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x>>=");
+  T tmp = lhs.Get ();
+  tmp >>= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator &= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x&=");
+  T tmp = lhs.Get ();
+  tmp &= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator |= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x|=");
+  T tmp = lhs.Get ();
+  tmp |= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> &operator ^= (TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x^=");
+  T tmp = lhs.Get ();
+  tmp ^= rhs;
+  lhs.Set (tmp);
+  return lhs;
+}
+template <typename T, typename U>
+TracedValue<T> operator + (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x+x");
+  return TracedValue<T> (lhs.Get () + rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator + (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x+");
+  return TracedValue<T> (lhs.Get () + rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator + (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("+x");
+  return TracedValue<T> (lhs + rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator - (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x-x");
+  return TracedValue<T> (lhs.Get () - rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator - (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x-");
+  return TracedValue<T> (lhs.Get () - rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator - (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("-x");
+  return TracedValue<T> (lhs - rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator * (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x*x");
+  return TracedValue<T> (lhs.Get () * rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator * (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x*");
+  return TracedValue<T> (lhs.Get () * rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator * (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("*x");
+  return TracedValue<T> (lhs - rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator / (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x/x");
+  return TracedValue<T> (lhs.Get () / rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator / (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x/");
+  return TracedValue<T> (lhs.Get () / rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator / (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("/x");
+  return TracedValue<T> (lhs / rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator % (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x%x");
+  return TracedValue<T> (lhs.Get () % rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator % (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x%");
+  return TracedValue<T> (lhs.Get () % rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator % (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("%x");
+  return TracedValue<T> (lhs % rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator ^ (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x^x");
+  return TracedValue<T> (lhs.Get () ^ rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator ^ (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x^");
+  return TracedValue<T> (lhs.Get () ^ rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator ^ (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("^x");
+  return TracedValue<T> (lhs ^ rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator | (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x|x");
+  return TracedValue<T> (lhs.Get () | rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator | (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x|");
+  return TracedValue<T> (lhs.Get () | rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator | (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("|x");
+  return TracedValue<T> (lhs | rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator & (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x&x");
+  return TracedValue<T> (lhs.Get () & rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator & (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x&");
+  return TracedValue<T> (lhs.Get () & rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator & (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("&x");
+  return TracedValue<T> (lhs & rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator << (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x<<x");
+  return TracedValue<T> (lhs.Get () << rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator << (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x<<");
+  return TracedValue<T> (lhs.Get () << rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator << (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE ("<<x");
+  return TracedValue<T> (lhs << rhs.Get ());
+}
+
+template <typename T, typename U>
+TracedValue<T> operator >> (const TracedValue<T> &lhs, const TracedValue<U> &rhs) {
+  TRACE ("x>>x");
+  return TracedValue<T> (lhs.Get () >> rhs.Get ());
+}
+template <typename T, typename U>
+TracedValue<T> operator >> (const TracedValue<T> &lhs, const U &rhs) {
+  TRACE ("x>>");
+  return TracedValue<T> (lhs.Get () >> rhs);
+}
+template <typename T, typename U>
+TracedValue<T> operator >> (const U &lhs, const TracedValue<T> &rhs) {
+  TRACE (">>x");
+  return TracedValue<T> (lhs >> rhs.Get ());
+}
+
+
+template <typename T>
+TracedValue<T> operator + (const TracedValue<T> &lhs) {
+  TRACE ("(+x)");
+  return TracedValue<T> (+lhs.Get ());
+}
+template <typename T>
+TracedValue<T> operator - (const TracedValue<T> &lhs) {
+  TRACE ("(-x)");
+  return TracedValue<T> (-lhs.Get ());
+}
+template <typename T>
+TracedValue<T> operator ~ (const TracedValue<T> &lhs) {
+  TRACE ("(~x)");
+  return TracedValue<T> (~lhs.Get ());
+}
+template <typename T>
+TracedValue<T> operator ! (const TracedValue<T> &lhs) {
+  TRACE ("(!x)");
+  return TracedValue<T> (!lhs.Get ());
+}
+
+
+} // namespace ns3
+
+#endif /* TRACED_VALUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/uinteger.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,65 @@
+#include "uinteger.h"
+#include "fatal-error.h"
+#include <sstream>
+
+namespace ns3 {
+
+Uinteger::Uinteger (uint64_t value)
+  : m_value (value)
+{}
+Uinteger::Uinteger ()
+{}
+void 
+Uinteger::Set (uint64_t value)
+{
+  m_value = value;
+}
+uint64_t 
+Uinteger::Get (void) const
+{
+  return m_value;
+}
+Uinteger::operator uint64_t () const
+{
+  return m_value;
+}
+std::ostream & operator << (std::ostream &os, const Uinteger &uinteger)
+{
+  os << uinteger.Get ();
+  return os;
+}
+std::istream & operator >> (std::istream &is, Uinteger &uinteger)
+{
+  uint64_t v;
+  is >> v;
+  uinteger.Set (v);
+  return is;
+}
+
+ATTRIBUTE_CONVERTER_IMPLEMENT(Uinteger);
+ATTRIBUTE_VALUE_IMPLEMENT(Uinteger);
+
+
+Ptr<const AttributeChecker> MakeUintegerChecker (uint64_t min, uint64_t max)
+{
+  struct Checker : public AttributeChecker
+  {
+    Checker (uint64_t minValue, uint64_t maxValue)
+      : m_minValue (minValue),
+      m_maxValue (maxValue) {}
+    virtual bool Check (Attribute value) const {
+      const UintegerValue *v = value.DynCast<const UintegerValue *> ();
+      if (v == 0)
+	{
+	  return false;
+	}
+      return v->Get ().Get () >= m_minValue && v->Get ().Get () <= m_maxValue;
+    }
+    uint64_t m_minValue;
+    uint64_t m_maxValue;
+  } *checker = new Checker (min, max);
+  return Ptr<const AttributeChecker> (checker, false);
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/uinteger.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,60 @@
+#ifndef UINTEGER_H
+#define UINTEGER_H
+
+#include "attribute.h"
+#include "attribute-helper.h"
+#include <stdint.h>
+
+namespace ns3 {
+
+class Uinteger
+{
+public:
+  Uinteger (uint64_t value);
+  Uinteger ();
+
+  void Set (uint64_t value);
+  uint64_t Get (void) const;
+
+  operator uint64_t () const;
+
+  ATTRIBUTE_CONVERTER_DEFINE (Uinteger);
+private:
+  uint64_t m_value;
+};
+
+std::ostream & operator << (std::ostream &os, const Uinteger &uinteger);
+std::istream & operator >> (std::istream &is, Uinteger &uinteger);
+
+ATTRIBUTE_VALUE_DEFINE (Uinteger);
+ATTRIBUTE_ACCESSOR_DEFINE (Uinteger);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeUintegerChecker (void);
+
+template <typename T>
+Ptr<const AttributeChecker> MakeUintegerChecker (uint64_t min);
+
+Ptr<const AttributeChecker> MakeUintegerChecker (uint64_t min, uint64_t max);
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+Ptr<const AttributeChecker> MakeUintegerChecker (void)
+{
+  return MakeUintegerChecker (std::numeric_limits<T>::min (),
+			      std::numeric_limits<T>::max ());
+}
+
+template <typename T>
+Ptr<const AttributeChecker> MakeUintegerChecker (uint64_t min)
+{
+  return MakeUintegerChecker (min,
+			      std::numeric_limits<T>::max ());
+}
+
+} // namespace ns3
+
+#endif /* UINTEGER_H */
--- a/src/core/wscript	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/core/wscript	Wed Feb 27 22:19:39 2008 +0100
@@ -31,6 +31,7 @@
         'callback-test.cc',
         'log.cc',
         'breakpoint.cc',
+        'object-base.cc',
         'ptr.cc',
         'object.cc',
         'test.cc',
@@ -52,6 +53,20 @@
         'type-traits-test.cc',
         'array-trace-resolver.cc',
         'type-id-default-value.cc',
+        'attribute.cc',
+        'boolean.cc',
+        'attribute-test.cc',
+        'integer.cc',
+        'uinteger.cc',
+        'enum.cc',
+        'double.cc',
+        'string.cc',
+        'object-factory.cc',
+        'object-vector.cc',
+        'global-value.cc',
+        'traced-callback.cc',
+        'trace-source-accessor.cc',
+        'config.cc',
         ]
 
     if sys.platform == 'win32':
@@ -68,6 +83,7 @@
         'system-wall-clock-ms.h',
         'empty.h',
         'callback.h',
+        'object-base.h',
         'ptr.h',
         'object.h',
         'log.h',
@@ -95,5 +111,21 @@
         'trace-doc.h',
         'int-to-type.h',
         'type-id-default-value.h',
+        'attribute.h',
+        'attribute-accessor-helper.h',
+        'boolean.h',
+        'integer.h',
+        'uinteger.h',
+        'double.h',
+        'enum.h',
+        'string.h',
+        'object-factory.h',
+        'attribute-helper.h',
+        'global-value.h',
+        'traced-callback.h',
+        'traced-value.h',
+        'trace-source-accessor.h',
+        'config.h',
+        'object-vector.h',
         ]
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma/csma-helper.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,59 @@
+#include "csma-helper.h"
+
+namespace ns3 {
+
+CsmaHelper::CsmaHelper ()
+{
+  m_queueFactory.SetTypeId ("DropTailQueue");
+  m_deviceFactory.SetTypeId ("CsmaNetDevice");
+  m_deviceChannel.SetTypeId ("CsmaChannel");
+}
+
+void 
+CsmaHelper::SetQueue (std::string type,
+		      std::string n1, Attribute v1,
+		      std::string n2, Attribute v2,
+		      std::string n3, Attribute v3,
+		      std::string n4, Attribute v4)
+{
+  m_queueFactory.SetTypeId (type);
+  m_queueFactory.Set (n1, v1);
+  m_queueFactory.Set (n2, v2);
+  m_queueFactory.Set (n3, v3);
+  m_queueFactory.Set (n4, v4);
+}
+
+  /**
+   * Set these parameters on each PointToPointNetDevice created
+   * by this helper.
+   */
+void 
+CsmaHelper::SetDeviceParameter (std::string n1, Attribute v1)
+{
+  m_deviceFactory.Set (n1, v1);
+}
+
+void 
+CsmaHelper::SetChannelParameter (std::string n1, Attribute v1)
+{
+  m_csmaFactory.Set (n1, v1);
+}
+
+NetDeviceContainer 
+CsmaHelper::Build (const NodeContainer &c)
+{
+  Ptr<CsmaChannel> channel = m_channelFactory.Create ()->GetObject<CsmaChannel> ();
+  return Build (c, channel);
+}
+
+NetDeviceContainer 
+CsmaHelper::Build (const NodeContainer &c, Ptr<CsmaChannel> channel)
+{
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); i++)
+    {
+      
+    }
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/csma/csma-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,38 @@
+#ifndef CSMA_HELPER_H
+#define CSMA_HELPER_H
+
+namespace ns3 {
+
+class CsmaHelper
+{
+public:
+  CsmaHelper ();
+
+  void SetQueue (std::string type,
+		 std::string n1 = "", Attribute v1 = Attribute (),
+		 std::string n2 = "", Attribute v2 = Attribute (),
+		 std::string n3 = "", Attribute v3 = Attribute (),
+		 std::string n4 = "", Attribute v4 = Attribute ());
+
+  /**
+   * Set these parameters on each PointToPointNetDevice created
+   * by this helper.
+   */
+  void SetDeviceParameter (std::string n1, Attribute v1);
+
+  void SetChannelParameter (std::string n1, Attribute v1);
+
+  NetDeviceContainer Build (const NodeContainer &c);
+
+  NetDeviceContainer Build (const NodeContainer &c, Ptr<CsmaChannel> channel);
+
+private:
+  ObjectFactory m_queueFactory;
+  ObjectFactory m_deviceFactory;
+  ObjectFactory m_channelFactory;
+};
+
+
+} // namespace ns3
+
+#endif /* CSMA_HELPER_H */
--- a/src/devices/csma/csma-ipv4-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/csma/csma-ipv4-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -26,6 +26,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/ipv4.h"
 #include "ns3/queue.h"
+#include "ns3/string.h"
 
 #include "csma-channel.h"
 #include "csma-net-device.h"
@@ -42,8 +43,10 @@
   Ptr<Queue> q = Queue::CreateDefault ();
 
   // assume full-duplex
-  Ptr<CsmaNetDevice> nd = CreateObject<CsmaNetDevice> (node, addr, 
-    ns3::CsmaNetDevice::IP_ARP, true, true);
+  Ptr<CsmaNetDevice> nd = CreateObjectWith<CsmaNetDevice> ("Node", node, 
+                                                           "Address", addr, 
+                                                           "EncapsulationMode", String ("IpArp"));
+  node->AddDevice (nd);
 
   nd->AddQueue(q);
   nd->Attach (channel);
@@ -58,15 +61,21 @@
 {
   Ptr<Queue> q = Queue::CreateDefault ();
 
-  Ptr<CsmaNetDevice> nd0 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::LLC,
-                                                  true, false);
+  Ptr<CsmaNetDevice> nd0 = CreateObjectWith<CsmaNetDevice> ("Node", n1, 
+                                                            "Address", addr,
+                                                            "EncapsulationMode", String ("Llc"));
+  n1->AddDevice (nd0);
+  nd0->SetSendEnable (true);
+  nd0->SetReceiveEnable (false);
   nd0->AddQueue(q);
   nd0->Attach (ch);
 
-  Ptr<CsmaNetDevice> nd1 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::LLC,
-                                                  false, true);
+  Ptr<CsmaNetDevice> nd1 = CreateObjectWith<CsmaNetDevice> ("Node", n1, 
+                                                            "Address", addr,
+                                                            "EncapsulationMode", String ("Llc"));
+  n1->AddDevice (nd1);
+  nd1->SetSendEnable (false);
+  nd1->SetReceiveEnable (true);
   nd1->AddQueue(q);
   nd1->Attach (ch);
 }
@@ -78,15 +87,22 @@
 {
   Ptr<Queue> q = Queue::CreateDefault ();
 
-  Ptr<CsmaNetDevice> nd0 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::RAW,
-                                                  true, false);
+  Ptr<CsmaNetDevice> nd0 = CreateObjectWith<CsmaNetDevice> ("Node", n1, 
+                                                            "Address", addr,
+                                                            "EncapsulationMode", String ("Raw"));
+  n1->AddDevice (nd0);
+  nd0->SetSendEnable (true);
+  nd0->SetReceiveEnable (false);
   nd0->AddQueue(q);
   nd0->Attach (ch);
 
-  Ptr<CsmaNetDevice> nd1 = CreateObject<CsmaNetDevice> (n1, addr,
-                                                  ns3::CsmaNetDevice::RAW,
-                                                  false, true);
+  Ptr<CsmaNetDevice> nd1 = CreateObjectWith<CsmaNetDevice> ("Node", n1, 
+                                                            "Address", addr,
+                                                            "EncapsulationMode", String ("Raw"));
+  n1->AddDevice (nd1);
+  nd1->SetSendEnable (false);
+  nd1->SetReceiveEnable (true);
+
   nd1->AddQueue(q);
   nd1->Attach (ch);
 }
--- a/src/devices/csma/csma-net-device.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/csma/csma-net-device.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -22,100 +22,83 @@
 #include "ns3/log.h"
 #include "ns3/queue.h"
 #include "ns3/simulator.h"
-#include "ns3/composite-trace-resolver.h"
-#include "csma-net-device.h"
-#include "csma-channel.h"
 #include "ns3/ethernet-header.h"
 #include "ns3/ethernet-trailer.h"
 #include "ns3/llc-snap-header.h"
 #include "ns3/error-model.h"
+#include "ns3/enum.h"
+#include "ns3/boolean.h"
+#include "ns3/trace-source-accessor.h"
+#include "csma-net-device.h"
+#include "csma-channel.h"
+
 
 NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
 
 namespace ns3 {
 
-CsmaTraceType::CsmaTraceType (enum Type type)
-  : m_type (type)
-{
-  NS_LOG_FUNCTION;
-}
+NS_OBJECT_ENSURE_REGISTERED (CsmaNetDevice);
 
-CsmaTraceType::CsmaTraceType ()
-  : m_type (RX)
-{
-  NS_LOG_FUNCTION;
-}
-
-void 
-CsmaTraceType::Print (std::ostream &os) const
+TypeId 
+CsmaNetDevice::GetTypeId (void)
 {
-  switch (m_type) {
-  case RX:
-    os << "dev-rx";
-    break;
-  case DROP:
-    os << "dev-drop";
-    break;
-  }
-}
-
-uint16_t 
-CsmaTraceType::GetUid (void)
-{
-  NS_LOG_FUNCTION;
-  static uint16_t uid = AllocateUid<CsmaTraceType> ("CsmaTraceType");
-  return uid;
-}
-
-std::string 
-CsmaTraceType::GetTypeName (void) const
-{
-  NS_LOG_FUNCTION;
-  return "ns3::CsmaTraceType";
+  static TypeId tid = TypeId ("CsmaNetDevice")
+    .SetParent<NetDevice> ()
+    .AddConstructor<CsmaNetDevice> ()
+    .AddAttribute ("Node", "The node with which this device is associated",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&CsmaNetDevice::m_node),
+                   MakePtrChecker<Node> ())
+    .AddAttribute ("Address", "The address of this device.",
+                   Mac48Address ("ff:ff:ff:ff:ff:ff"),
+                   MakeMac48AddressAccessor (&CsmaNetDevice::m_address),
+                   MakeMac48AddressChecker ())
+    .AddAttribute ("EncapsulationMode", "The mode of link-layer encapsulation to use.",
+                   Enum (LLC),
+                   MakeEnumAccessor (&CsmaNetDevice::m_encapMode),
+                   MakeEnumChecker (ETHERNET_V1, "EthernetV1",
+                                    IP_ARP, "IpArp",
+                                    RAW, "Raw",
+                                    LLC, "Llc"))
+    .AddAttribute ("SendEnable", "should tx be enabled ?",
+                   Boolean (true),
+                   MakeBooleanAccessor (&CsmaNetDevice::m_sendEnable),
+                   MakeBooleanChecker ())
+    .AddAttribute ("ReceiveEnable", "should rx be enabled ?",
+                   Boolean (true),
+                   MakeBooleanAccessor (&CsmaNetDevice::m_receiveEnable),
+                   MakeBooleanChecker ())
+    .AddAttribute ("DataRate", "XXX",
+                   DataRate (0xffffffff),
+                   MakeDataRateAccessor (&CsmaNetDevice::m_bps),
+                   MakeDataRateChecker ())
+    .AddAttribute ("RxErrorModel", "XXX",
+                   Ptr<ErrorModel> (0),
+                   MakePtrAccessor (&CsmaNetDevice::m_receiveErrorModel),
+                   MakePtrChecker<ErrorModel> ())
+    .AddAttribute ("TxQueue", "XXX",
+                   Ptr<Queue> (0),
+                   MakePtrAccessor (&CsmaNetDevice::m_queue),
+                   MakePtrChecker<Queue> ())
+    .AddTraceSource ("Rx", "Receive MAC packet.",
+                     MakeTraceSourceAccessor (&CsmaNetDevice::m_rxTrace))
+    .AddTraceSource ("Drop", "Drop MAC packet.",
+                     MakeTraceSourceAccessor (&CsmaNetDevice::m_dropTrace))
+    ;
+  return tid;
 }
 
-enum CsmaTraceType::Type 
-CsmaTraceType::Get (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_type;
-}
-
-CsmaNetDevice::CsmaNetDevice (Ptr<Node> node)
-  : NetDevice (node, Mac48Address::Allocate ()),
-    m_bps (DataRate (0xffffffff)),
-    m_receiveErrorModel (0)
+CsmaNetDevice::CsmaNetDevice ()
+  : m_name (""),
+    m_linkUp (false),
+    m_mtu (0xffff)
 {
   NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-  m_encapMode = IP_ARP;
-  Init(true, true);
-}
-
-CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Mac48Address addr, 
-                              CsmaEncapsulationMode encapMode) 
-  : NetDevice(node, addr), 
-    m_bps (DataRate (0xffffffff)),
-    m_receiveErrorModel (0)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-  m_encapMode = encapMode;
-
-  Init(true, true);
-}
-
-CsmaNetDevice::CsmaNetDevice (Ptr<Node> node, Mac48Address addr, 
-                              CsmaEncapsulationMode encapMode,
-                              bool sendEnable, bool receiveEnable) 
-  : NetDevice(node, addr), 
-    m_bps (DataRate (0xffffffff))
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-  m_encapMode = encapMode;
-
-  Init(sendEnable, receiveEnable);
+  NS_LOG_PARAMS (this);
+  m_txMachineState = READY;
+  m_tInterframeGap = Seconds(0);
+  m_channel = 0; 
 }
 
 CsmaNetDevice::~CsmaNetDevice()
@@ -129,43 +112,10 @@
 {
   NS_LOG_FUNCTION;
   m_channel = 0;
+  m_node = 0;
   NetDevice::DoDispose ();
 }
 
-//
-// Assignment operator for CsmaNetDevice.
-//
-// This uses the non-obvious trick of taking the source net device passed by
-// value instead of by reference.  This causes the copy constructor to be
-// invoked (where the real work is done -- see above).  All we have to do
-// here is to return the newly constructed net device.
-//
-/*
-CsmaNetDevice&
-CsmaNetDevice::operator= (const CsmaNetDevice nd)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << &nd);
-  return *this;
-}
-*/
-
-void 
-CsmaNetDevice::Init(bool sendEnable, bool receiveEnable)
-{
-  NS_LOG_FUNCTION;
-  m_txMachineState = READY;
-  m_tInterframeGap = Seconds(0);
-  m_channel = 0; 
-  m_queue = 0;
-
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-  EnableMulticast (Mac48Address ("01:00:5e:00:00:00"));
-
-  SetSendEnable (sendEnable);
-  SetReceiveEnable (receiveEnable);
-}
-
 void
 CsmaNetDevice::SetSendEnable (bool sendEnable)
 {
@@ -302,58 +252,6 @@
   return true;
 }
 
-bool
-CsmaNetDevice::DoNeedsArp (void) const
-{
-  NS_LOG_FUNCTION;
-  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
-    {
-      return true;
-    } 
-  else 
-    {
-      return false;
-    }
-}
-
-bool
-CsmaNetDevice::SendTo (Ptr<Packet> packet, 
-                       const Address& dest, 
-                       uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_LOGIC ("p=" << packet);
-  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
-
-  NS_ASSERT (IsLinkUp ());
-
-  // Only transmit if send side of net device is enabled
-  if (!IsSendEnabled())
-    return false;
-
-  Mac48Address destination = Mac48Address::ConvertFrom (dest);
-  AddHeader(packet, destination, protocolNumber);
-
-  // Place the packet to be sent on the send queue
-  if (m_queue->Enqueue(packet) == false )
-    {
-      return false;
-    }
-  // If the device is idle, we need to start a transmission. Otherwise,
-  // the transmission will be started when the current packet finished
-  // transmission (see TransmitCompleteEvent)
-  if (m_txMachineState == READY) 
-    {
-      // Store the next packet to be transmitted
-      m_currentPkt = m_queue->Dequeue ();
-      if (m_currentPkt != 0)
-        {
-          TransmitStart();
-        }
-    }
-  return true;
-}
-
 void
 CsmaNetDevice::TransmitStart ()
 {
@@ -486,26 +384,6 @@
     }
 }
 
-Ptr<TraceResolver>
-CsmaNetDevice::GetTraceResolver (void) const
-{
-  NS_LOG_FUNCTION;
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddComposite ("queue", m_queue);
-  resolver->AddSource ("rx",
-                       TraceDoc ("receive MAC packet",
-                                 "Ptr<const Packet>", "packet received"),
-                       m_rxTrace,
-                       CsmaTraceType (CsmaTraceType::RX));
-  resolver->AddSource ("drop",
-                       TraceDoc ("drop MAC packet",
-                                 "Ptr<const Packet>", "packet dropped"),
-                       m_dropTrace,
-                       CsmaTraceType (CsmaTraceType::DROP));
-  resolver->SetParentResolver (NetDevice::GetTraceResolver ());
-  return resolver;
-}
-
 bool
 CsmaNetDevice::Attach (Ptr<CsmaChannel> ch)
 {
@@ -540,7 +418,6 @@
   NS_LOG_PARAM ("(" << em << ")");
   
   m_receiveErrorModel = em; 
-  AggregateObject (em);
 }
 
 void
@@ -565,7 +442,7 @@
 
   if (m_encapMode == RAW)
     {
-      ForwardUp (packet, 0, GetBroadcast ());
+      m_rxCallback (this, packet, 0, GetBroadcast ());
       m_dropTrace (packet);
       return;
     }
@@ -636,12 +513,100 @@
           NS_ASSERT (false);
           break;
         }
-      ForwardUp (packet, protocol, header.GetSource ());
+      m_rxCallback (this, packet, protocol, header.GetSource ());
+    }
+}
+
+Ptr<Queue>
+CsmaNetDevice::GetQueue(void) const 
+{ 
+  NS_LOG_FUNCTION;
+  return m_queue;
+}
+
+void
+CsmaNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
     }
 }
 
+void 
+CsmaNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+CsmaNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+CsmaNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+CsmaNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+CsmaNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+CsmaNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+bool 
+CsmaNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+CsmaNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+CsmaNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+CsmaNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+CsmaNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
 Address
-CsmaNetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
+CsmaNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+CsmaNetDevice::IsMulticast (void) const
+{
+  return false;
+}
+Address 
+CsmaNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+CsmaNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
 {
   NS_LOG_FUNCTION;
   NS_LOG_PARAMS (this << multicastGroup);
@@ -692,20 +657,67 @@
 
   return etherAddr;
 }
+bool 
+CsmaNetDevice::IsPointToPoint (void) const
+{
+  return false;
+}
+bool 
+CsmaNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION;
+  NS_LOG_LOGIC ("p=" << packet);
+  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
 
-Ptr<Queue>
-CsmaNetDevice::GetQueue(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_queue;
+  NS_ASSERT (IsLinkUp ());
+
+  // Only transmit if send side of net device is enabled
+  if (!IsSendEnabled())
+    return false;
+
+  Mac48Address destination = Mac48Address::ConvertFrom (dest);
+  AddHeader(packet, destination, protocolNumber);
+
+  // Place the packet to be sent on the send queue
+  if (m_queue->Enqueue(packet) == false )
+    {
+      return false;
+    }
+  // If the device is idle, we need to start a transmission. Otherwise,
+  // the transmission will be started when the current packet finished
+  // transmission (see TransmitCompleteEvent)
+  if (m_txMachineState == READY) 
+    {
+      // Store the next packet to be transmitted
+      m_currentPkt = m_queue->Dequeue ();
+      if (m_currentPkt != 0)
+        {
+          TransmitStart();
+        }
+    }
+  return true;
+}
+Ptr<Node> 
+CsmaNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+CsmaNetDevice::NeedsArp (void) const
+{
+  if ((m_encapMode == IP_ARP) || (m_encapMode == LLC))
+    {
+      return true;
+    } 
+  else 
+    {
+      return false;
+    }
+}
+void 
+CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
 }
 
-Ptr<Channel>
-CsmaNetDevice::DoGetChannel(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_channel;
-}
-
-
 } // namespace ns3
--- a/src/devices/csma/csma-net-device.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/csma/csma-net-device.h	Wed Feb 27 22:19:39 2008 +0100
@@ -29,7 +29,7 @@
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 #include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
 #include "ns3/ptr.h"
@@ -43,29 +43,6 @@
 class ErrorModel;
 
 /**
- * \brief hold in a TraceContext the type of trace source from a CsmaNetDevice
- */
-class CsmaTraceType : public TraceContextElement
-{
-public:
-  enum Type {
-    RX, 
-    DROP
-  };
-  CsmaTraceType (enum Type type);
-  CsmaTraceType ();
-  void Print (std::ostream &os) const;
-  static uint16_t GetUid (void);
-  std::string GetTypeName (void) const;
-  /**
-   * \returns the type of the trace source which generated an event.
-   */
-  enum Type Get (void) const;
-private:
-  enum Type m_type;
-};
-
-/**
  * \class CsmaNetDevice
  * \brief A Device for a Csma Network Link.
  *
@@ -84,9 +61,10 @@
  * devices
  *
  */
-class CsmaNetDevice : public NetDevice {
+class CsmaNetDevice : public NetDevice 
+{
 public:
-
+  static TypeId GetTypeId (void);
   /**
    * Enumeration of the types of packets supported in the class.
    *
@@ -98,7 +76,6 @@
   LLC,         /**< LLC packet encapsulation */  
 };
 
-  CsmaNetDevice (Ptr<Node> node);
   /**
    * Construct a CsmaNetDevice
    *
@@ -106,29 +83,10 @@
    * parameter the Node to which this device is connected.  Ownership of the
    * Node pointer is not implied and the node must not be deleted.
    *
-   * \param node the Node to which this device is connected.
-   * \param addr The source MAC address of the net device.
-   * \param pktType the type of encapsulation
    */
-  CsmaNetDevice (Ptr<Node> node, Mac48Address addr, CsmaEncapsulationMode pktType);
+  CsmaNetDevice ();
 
   /**
-   * Construct a CsmaNetDevice
-   *
-   * This is the constructor for the CsmaNetDevice.  It takes as a
-   * parameter the Node to which this device is connected.  Ownership of the
-   * Node pointer is not implied and the node must not be deleted.
-   *
-   * \param node the Node to which this device is connected.
-   * \param addr The source MAC address of the net device.
-   * \param pktType the type of encapsulation
-   * \param sendEnable whether this device is able to send
-   * \param receiveEnable whether this device is able to receive
-   */
-  CsmaNetDevice (Ptr<Node> node, Mac48Address addr,
-                   CsmaEncapsulationMode pktType,
-                   bool sendEnable, bool receiveEnable);
-  /**
    * Destroy a CsmaNetDevice
    *
    * This is the destructor for the CsmaNetDevice.
@@ -216,6 +174,28 @@
    */
   void Receive (Ptr<Packet> p);
 
+  bool IsSendEnabled (void);
+  bool IsReceiveEnabled (void);
+
+  void SetSendEnable (bool);
+  void SetReceiveEnable (bool);
+
+
+  // inherited from NetDevice base class.
+  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;
   /**
    * @brief Make and return a MAC multicast address using the provided
    *        multicast group
@@ -229,13 +209,6 @@
    * to an EUI-48-based CSMA device.  This MAC address is encapsulated in an
    *  abstract Address to avoid dependencies on the exact address format.
    *
-   * A default imlementation of MakeMulticastAddress is provided, but this
-   * method simply NS_ASSERTS.  In the case of net devices that do not support
-   * multicast, clients are expected to test NetDevice::IsMulticast and avoid
-   * attempting to map multicast packets.  Subclasses of NetDevice that do
-   * support multicasting are expected to override this method and provide an
-   * implementation appropriate to the particular device.
-   *
    * @param multicastGroup The IP address for the multicast group destination
    * of the packet.
    * @return The MAC multicast Address used to send packets to the provided
@@ -245,23 +218,15 @@
    * @see Mac48Address
    * @see Address
    */
-  Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
-
-  bool IsSendEnabled (void);
-  bool IsReceiveEnabled (void);
-
-  void SetSendEnable (bool);
-  void SetReceiveEnable (bool);
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
+  virtual bool IsPointToPoint (void) const;
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
 
 protected:
-  virtual bool DoNeedsArp (void) const;
   virtual void DoDispose (void);
-  /**
-   * Create a Trace Resolver for events in the net device.
-   * (NOT TESTED)
-   * @see class TraceResolver
-   */
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
 
   /**
    * Get a copy of the attached Queue.
@@ -273,15 +238,6 @@
    */
   Ptr<Queue> GetQueue (void) const; 
   /**
-   * Get a copy of the attached Channel
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the connected channel
-   *
-   * \return a pointer to the channel
-   */
-  virtual Ptr<Channel> DoGetChannel (void) const;
-  /**
    * Adds the necessary headers and trailers to a packet of data in order to
    * respect the packet type
    *
@@ -312,22 +268,6 @@
    * Initializes variablea when construction object.
    */
   void Init (bool sendEnable, bool receiveEnable);
-  /**
-   * Send a Packet on the Csma network
-   *
-   * This method does not use a destination address since all packets
-   * are broadcast to all NetDevices attached to the channel. Packet
-   * should contain all needed headers at this time.
-   *
-   * If the device is ready to transmit, the next packet is read off
-   * of the queue and stored locally until it has been transmitted.
-   *
-   * \param p a reference to the packet to send
-   * \param dest destination address
-   * \param protocolNumber -- this parameter is not used here
-   * \return true if success, false on failure
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address& dest, uint16_t protocolNumber);
 
   /**
    * Start Sending a Packet Down the Wire.
@@ -388,6 +328,7 @@
    *
    */
   void TransmitAbort (void);
+  void NotifyLinkUp (void);
 
   /** 
    * Device ID returned by the attached functions. It is used by the
@@ -478,9 +419,17 @@
    * @see class CallBackTraceSource
    * @see class TraceResolver
    */
-  CallbackTraceSource<Ptr<const Packet> > m_rxTrace;
-  CallbackTraceSource<Ptr<const Packet> > m_dropTrace;
+  TracedCallback<Ptr<const Packet> > m_rxTrace;
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
 
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
 }; // namespace ns3
--- a/src/devices/csma/csma-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/csma/csma-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -46,10 +46,11 @@
 CsmaTopology::AddCsmaEthernetNode(
   Ptr<Node> n1,
   Ptr<CsmaChannel> ch,
-  MacAddress addr)
+  Mac48Address addr)
 {
-  Ptr<CsmaNetDevice> nd1 = CreateObject<CsmaNetDevice> (n1, addr, 
-                                                      ns3::CsmaNetDevice::ETHERNET_V1);
+  Ptr<CsmaNetDevice> nd1 = CreateObjectWith<CsmaNetDevice> ("Node", Ptr<Node> (n1), 
+                                                            "Address", addr, 
+                                                            "EncapsulationMode", "EthernetV1");
 
   Ptr<Queue> q = Queue::CreateDefault ();
   nd1->AddQueue(q);
@@ -60,8 +61,8 @@
 
 Ptr<PacketSocket>
 CsmaTopology::ConnectPacketSocket(Ptr<PacketSocketApp> app, 
-                                        Ptr<CsmaNetDevice> ndSrc,
-                                        Ptr<CsmaNetDevice> ndDest)
+                                  Ptr<CsmaNetDevice> ndSrc,
+                                  Ptr<CsmaNetDevice> ndDest)
 {
   Ptr<PacketSocket> socket = CreateObject<PacketSocket> ();
   socket->Bind(ndSrc);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-helper.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,53 @@
+#include "point-to-point-helper.h"
+#include "point-to-point-net-device.h"
+#include "point-to-point-channel.h"
+#include "ns3/queue.h"
+
+namespace ns3 {
+
+
+PointToPointHelper::PointToPointHelper ()
+{}
+
+void 
+PointToPointHelper::SetQueue (std::string type,
+			      std::string n1, Attribute v1,
+			      std::string n2, Attribute v2,
+			      std::string n3, Attribute v3,
+			      std::string n4, Attribute v4)
+{
+  m_queueFactory.SetTypeId (type);
+  m_queueFactory.Set (n1, v1);
+  m_queueFactory.Set (n2, v2);
+  m_queueFactory.Set (n3, v3);
+  m_queueFactory.Set (n4, v4);
+}
+
+NetDeviceContainer 
+PointToPointHelper::Build (NodeContainer c)
+{
+  NS_ASSERT (c.GetN () == 2);
+  return Build (c.Get (0), c.Get (1));
+}
+NetDeviceContainer 
+PointToPointHelper::Build (Ptr<Node> a, Ptr<Node> b)
+{
+  NetDeviceContainer container;
+
+  Ptr<PointToPointNetDevice> devA = CreateObject<PointToPointNetDevice> (a);
+  Ptr<Queue> queueA = m_queueFactory.Create ()->GetObject<Queue> ();
+  devA->AddQueue (queueA);
+  Ptr<PointToPointNetDevice> devB = CreateObject<PointToPointNetDevice> (b);
+  Ptr<Queue> queueB = m_queueFactory.Create ()->GetObject<Queue> ();
+  devB->AddQueue (queueB);
+  Ptr<PointToPointChannel> channel = CreateObject<PointToPointChannel> ();
+  devA->Attach (channel);
+  devB->Attach (channel);
+  container.Add (devA);
+  container.Add (devB);
+
+  return container;
+}
+
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/point-to-point/point-to-point-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,42 @@
+#ifndef POINT_TO_POINT_HELPER_H
+#define POINT_TO_POINT_HELPER_H
+
+#include "ns3/object-factory.h"
+#include "ns3/net-device-container.h"
+#include "ns3/node-container.h"
+#include <string>
+
+namespace ns3 {
+
+class PointToPointHelper
+{
+public:
+  // by default, create queues of type DropTailQueue.
+  PointToPointHelper ();
+
+  void SetQueue (std::string type,
+		 std::string n1 = "", Attribute v1 = Attribute (),
+		 std::string n2 = "", Attribute v2 = Attribute (),
+		 std::string n3 = "", Attribute v3 = Attribute (),
+		 std::string n4 = "", Attribute v4 = Attribute ());
+
+  /**
+   * Set these parameters on each PointToPointNetDevice created
+   * by this helper.
+   */
+  void SetDeviceParameters (std::string n1, Attribute v1,
+			    std::string n2 = "", Attribute v2 = Attribute (),
+			    std::string n3 = "", Attribute v3 = Attribute (),
+			    std::string n4 = "", Attribute v4 = Attribute ());
+
+  NetDeviceContainer Build (NodeContainer c);
+  NetDeviceContainer Build (Ptr<Node> a, Ptr<Node> b);
+
+private:
+  ObjectFactory m_queueFactory;
+};
+
+
+} // namespace ns3
+
+#endif /* POINT_TO_POINT_HELPER_H */
--- a/src/devices/point-to-point/point-to-point-net-device.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,10 +23,10 @@
 #include "ns3/log.h"
 #include "ns3/queue.h"
 #include "ns3/simulator.h"
-#include "ns3/composite-trace-resolver.h"
 #include "ns3/mac48-address.h"
 #include "ns3/llc-snap-header.h"
 #include "ns3/error-model.h"
+#include "ns3/trace-source-accessor.h"
 #include "point-to-point-net-device.h"
 #include "point-to-point-channel.h"
 
@@ -34,91 +34,63 @@
 
 namespace ns3 {
 
-DataRateDefaultValue PointToPointNetDevice::g_defaultRate(
-           "PointToPointLinkDataRate", 
-           "The default data rate for point to point links",
-           DataRate ("10Mb/s"));
+NS_OBJECT_ENSURE_REGISTERED (PointToPointNetDevice);
 
-PointToPointTraceType::PointToPointTraceType (enum Type type)
-  : m_type (type)
+TypeId 
+PointToPointNetDevice::GetTypeId (void)
 {
-  NS_LOG_FUNCTION;
-}
-PointToPointTraceType::PointToPointTraceType ()
-  : m_type (RX)
-{
-  NS_LOG_FUNCTION;
+  static TypeId tid = TypeId ("PointToPointNetDevice")
+    .SetParent<NetDevice> ()
+    .AddConstructor<PointToPointNetDevice> ()
+    .AddAttribute ("Node", "The node with which this device is associated",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&PointToPointNetDevice::m_node),
+                   MakePtrChecker<Node> ())
+    .AddAttribute ("Address", "The address of this device.",
+                   Mac48Address ("ff:ff:ff:ff:ff:ff"),
+                   MakeMac48AddressAccessor (&PointToPointNetDevice::m_address),
+                   MakeMac48AddressChecker ())
+    .AddAttribute ("DataRate", "The default data rate for point to point links",
+                   DataRate ("10Mb/s"),
+                   MakeDataRateAccessor (&PointToPointNetDevice::m_bps),
+                   MakeDataRateChecker ())
+    .AddAttribute ("RxErrorModel", "XXX",
+                   Ptr<ErrorModel> (0),
+                   MakePtrAccessor (&PointToPointNetDevice::m_receiveErrorModel),
+                   MakePtrChecker<ErrorModel> ())
+    .AddAttribute ("TxQueue", "XXX",
+                   Ptr<Queue> (0),
+                   MakePtrAccessor (&PointToPointNetDevice::m_queue),
+                   MakePtrChecker<Queue> ())
+    .AddAttribute ("InterframeGap", "XXX",
+                   Seconds (0.0),
+                   MakeTimeAccessor (&PointToPointNetDevice::m_tInterframeGap),
+                   MakeTimeChecker ())
+    .AddTraceSource ("Rx", "Receive MAC packet.",
+                     MakeTraceSourceAccessor (&PointToPointNetDevice::m_rxTrace))
+    .AddTraceSource ("Drop", "Drop MAC packet.",
+                     MakeTraceSourceAccessor (&PointToPointNetDevice::m_dropTrace))
+
+    ;
+  return tid;
 }
 
-void 
-PointToPointTraceType::Print (std::ostream &os) const
-{
-  switch (m_type) {
-  case RX:
-    os << "dev-rx";
-    break;
-  case DROP:
-    os << "dev-drop";
-    break;
-  }
-}
 
-uint16_t 
-PointToPointTraceType::GetUid (void)
-{
-  NS_LOG_FUNCTION;
-  static uint16_t uid = AllocateUid<PointToPointTraceType> ("PointToPointTraceType");
-  return uid;
-}
-
-std::string 
-PointToPointTraceType::GetTypeName (void) const
+PointToPointNetDevice::PointToPointNetDevice () 
+: 
+  m_txMachineState (READY),
+  m_channel (0), 
+  m_name (""),
+  m_linkUp (false),
+  m_mtu (0xffff)
 {
   NS_LOG_FUNCTION;
-  return "ns3::PointToPointTraceType";
-}
-
-enum PointToPointTraceType::Type
-PointToPointTraceType::Get (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_type;
+  NS_LOG_PARAMS (this);
 }
 
-PointToPointNetDevice::PointToPointNetDevice (Ptr<Node> node,
-                                              const DataRate& rate) 
-: 
-  NetDevice(node, Mac48Address::Allocate ()), 
-  m_txMachineState (READY),
-  m_bps (rate),
-  m_tInterframeGap (Seconds(0)),
-  m_channel (0), 
-  m_queue (0),
-  m_rxTrace (),
-  m_dropTrace (),
-  m_receiveErrorModel (0)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
-//
-// XXX BUGBUG
-//
-// You _must_ support broadcast to get any sort of packet from the ARP layer.
-//
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-//
-// We want to allow multicast packets to flow across this link
-//
-  EnableMulticast (Mac48Address ("01:00:5e:00:00:00"));
-  EnablePointToPoint();
-}
-
-PointToPointNetDevice::~PointToPointNetDevice()
-{
-  NS_LOG_FUNCTION;
-  m_queue = 0;
-  m_receiveErrorModel = 0;
-}
+PointToPointNetDevice::~PointToPointNetDevice ()
+{}
 
 void 
 PointToPointNetDevice::AddHeader(Ptr<Packet> p, uint16_t protocolNumber)
@@ -144,7 +116,9 @@
 void PointToPointNetDevice::DoDispose()
 {
   NS_LOG_FUNCTION;
+  m_node = 0;
   m_channel = 0;
+  m_receiveErrorModel = 0;
   NetDevice::DoDispose ();
 }
 
@@ -163,40 +137,7 @@
   m_tInterframeGap = t;
 }
 
-bool PointToPointNetDevice::SendTo (Ptr<Packet> packet, const Address& dest, 
-                                    uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  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 ());
-  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
-      m_queue->Enqueue (packet);
-      packet = m_queue->Dequeue ();
-      return TransmitStart (packet);
-    }
-  else
-    {
-      return m_queue->Enqueue(packet);
-    }
-}
-
-  bool
+bool
 PointToPointNetDevice::TransmitStart (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION;
@@ -240,26 +181,6 @@
   TransmitStart(p);
 }
 
-Ptr<TraceResolver> 
-PointToPointNetDevice::GetTraceResolver (void) const
-{
-  NS_LOG_FUNCTION;
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddComposite ("queue", m_queue);
-  resolver->AddSource ("rx",
-                       TraceDoc ("receive MAC packet",
-                                 "Ptr<const Packet>", "packet received"),
-                       m_rxTrace,
-                       PointToPointTraceType (PointToPointTraceType::RX));
-  resolver->AddSource ("drop",
-                       TraceDoc ("drop MAC packet",
-                                 "Ptr<const Packet>", "packet dropped"),
-                       m_dropTrace,
-                       PointToPointTraceType (PointToPointTraceType::DROP));
-  resolver->SetParentResolver (NetDevice::GetTraceResolver ());
-  return resolver;
-}
-
 bool 
 PointToPointNetDevice::Attach (Ptr<PointToPointChannel> ch)
 {
@@ -320,7 +241,7 @@
     {
       m_rxTrace (packet);
       ProcessHeader(packet, protocol);
-      ForwardUp (packet, protocol, GetBroadcast ());
+      m_rxCallback (this, packet, protocol, GetBroadcast ());
     }
 }
 
@@ -330,16 +251,144 @@
   return m_queue;
 }
 
-Ptr<Channel> PointToPointNetDevice::DoGetChannel(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_channel;
+void
+PointToPointNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
+    }
 }
 
-bool PointToPointNetDevice::DoNeedsArp (void) const
+void 
+PointToPointNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+PointToPointNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+PointToPointNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+PointToPointNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+PointToPointNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+PointToPointNetDevice::GetAddress (void) const
 {
-  NS_LOG_FUNCTION;
+  return m_address;
+}
+bool 
+PointToPointNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+PointToPointNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+PointToPointNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+PointToPointNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+PointToPointNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
+Address
+PointToPointNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+PointToPointNetDevice::IsMulticast (void) const
+{
   return false;
 }
+Address 
+PointToPointNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+PointToPointNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+bool 
+PointToPointNetDevice::IsPointToPoint (void) const
+{
+  return true;
+}
+bool 
+PointToPointNetDevice::Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
+{
+    NS_LOG_FUNCTION;
+  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 ());
+  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
+      m_queue->Enqueue (packet);
+      packet = m_queue->Dequeue ();
+      return TransmitStart (packet);
+    }
+  else
+    {
+      return m_queue->Enqueue(packet);
+    }
+}
+Ptr<Node> 
+PointToPointNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+PointToPointNetDevice::NeedsArp (void) const
+{
+  return false;
+}
+void 
+PointToPointNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
+}
+
 
 } // namespace ns3
--- a/src/devices/point-to-point/point-to-point-net-device.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-net-device.h	Wed Feb 27 22:19:39 2008 +0100
@@ -27,11 +27,11 @@
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 #include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
 #include "ns3/data-rate.h"
-#include "ns3/default-value.h"
 #include "ns3/ptr.h"
+#include "ns3/mac48-address.h"
 
 namespace ns3 {
 
@@ -40,29 +40,6 @@
 class ErrorModel;
 
 /**
- * \brief hold in a TraceContext the type of trace source from a PointToPointNetDevice
- */
-class PointToPointTraceType : public TraceContextElement
-{
-public:
-  enum Type {
-    RX,
-    DROP
-  };
-  PointToPointTraceType (enum Type type);
-  PointToPointTraceType ();
-  void Print (std::ostream &os) const;
-  static uint16_t GetUid (void);
-  std::string GetTypeName (void) const;
-  /**
-   * \returns the type of the trace source which generated an event.
-   */
-  enum Type Get (void) const;
-private:
-  enum Type m_type;
-};
-
-/**
  * \class PointToPointNetDevice
  * \brief A Device for a Point to Point Network Link.
  *
@@ -74,8 +51,11 @@
  * include a queue, data rate, and interframe transmission gap (the 
  * propagation delay is set in the PointToPointChannel).
  */
-class PointToPointNetDevice : public NetDevice {
+class PointToPointNetDevice : public NetDevice 
+{
 public:
+  static TypeId GetTypeId (void);
+
   /**
    * Construct a PointToPointNetDevice
    *
@@ -84,11 +64,8 @@
    * as well as an optional DataRate object.
    *
    * @see PointToPointTopology::AddPointToPointLink ()
-   * @param node the Node to which this device is connected.
-   * @param rate (optional) DataRate object
    */
-  PointToPointNetDevice (Ptr<Node> node,
-                         const DataRate& rate = g_defaultRate.GetValue());
+  PointToPointNetDevice ();
   /**
    * Destroy a PointToPointNetDevice
    *
@@ -168,13 +145,29 @@
    */
   void Receive (Ptr<Packet> p);
 
+  // inherited from NetDevice base class.
+  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 Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
 private:
-  /**
-   * Create a Trace Resolver for events in the net device.
-   *
-   * @see class TraceResolver
-   */
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
 
   virtual void DoDispose (void);
   /**
@@ -188,28 +181,6 @@
    */
   Ptr<Queue> GetQueue(void) const; 
 
-  /**
-   * Get a copy of the attached Channel
-   *
-   * This method is provided for any derived class that may need to get
-   * direct access to the connected channel
-   *
-   * @see PointToPointChannel
-   * @returns a pointer to the channel
-   */
-  virtual Ptr<Channel> DoGetChannel(void) const;
-
-  /**
-   * Set a new default data rate
-   */
-  static void SetDefaultRate(const DataRate&);
-
-  /** 
-   * Get the current default rate.
-   * @returns a const reference to current default
-   */
-  static const DataRate& GetDefaultRate();
-
 private:
   /**
    * Adds the necessary headers and trailers to a packet of data in order to
@@ -224,21 +195,6 @@
    */
   bool ProcessHeader(Ptr<Packet> p, uint16_t& param);
   /**
-   * Send a Packet Down the Wire.
-   *
-   * The SendTo method is defined as the standard way that the level three
-   * protocol uses to tell a NetDevice to send a packet.  SendTo is declared
-   * as abstract in the NetDevice class and we declare it here.
-   *
-   * @see NetDevice
-   * @param p a reference to the packet to send
-   * @param dest a reference to the Address of the destination device
-   * @param protocolNumber Protocol Number used to find protocol touse
-   * @returns true if success, false on failure
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address& dest, 
-                       uint16_t protocolNumber);
-  /**
    * Start Sending a Packet Down the Wire.
    *
    * The TransmitStart method is the method that is used internally in the
@@ -262,7 +218,8 @@
    *
    */
   void TransmitComplete(void);
-  virtual bool DoNeedsArp (void) const;
+  void NotifyLinkUp (void);
+
   /**
    * Enumeration of the states of the transmit machine of the net device.
    */
@@ -309,7 +266,7 @@
    * @see class CallBackTraceSource
    * @see class TraceResolver
    */
-  CallbackTraceSource<Ptr<const Packet> > m_rxTrace;
+  TracedCallback<Ptr<const Packet> > m_rxTrace;
   /**
    * The trace source for the packet drop events that the device can
    * fire.
@@ -317,19 +274,24 @@
    * @see class CallBackTraceSource
    * @see class TraceResolver
    */
-  CallbackTraceSource<Ptr<const Packet> > m_dropTrace;
-  /** 
-   * Default data rate.  Used for all newly created p2p net devices
-   */
-   static DataRateDefaultValue g_defaultRate;
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
 
   /**
    * Error model for receive packet events
    */
   Ptr<ErrorModel> m_receiveErrorModel;
+
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif // POINT_TO_POINT_NET_DEVICE_H
 
--- a/src/devices/point-to-point/point-to-point-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/point-to-point/point-to-point-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -47,13 +47,17 @@
 {
   Ptr<PointToPointChannel> channel = CreateObject<PointToPointChannel> (bps, delay);
 
-  Ptr<PointToPointNetDevice> net1 = CreateObject<PointToPointNetDevice> (n1);
+  Ptr<PointToPointNetDevice> net1 = CreateObjectWith<PointToPointNetDevice> ("Node", n1, 
+                                                                             "Address", Mac48Address::Allocate ());
+  n1->AddDevice (net1);
 
   Ptr<Queue> q = Queue::CreateDefault ();
   net1->AddQueue(q);
   net1->Attach (channel);
   
-  Ptr<PointToPointNetDevice> net2 = CreateObject<PointToPointNetDevice> (n2);
+  Ptr<PointToPointNetDevice> net2 = CreateObjectWith<PointToPointNetDevice> ("Node", n2, 
+                                                                             "Address", Mac48Address::Allocate ());
+  n2->AddDevice (net2);
 
   q = Queue::CreateDefault ();
   net2->AddQueue(q);
--- a/src/devices/wifi/propagation-loss-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/wifi/propagation-loss-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -286,8 +286,12 @@
    *      
    * rx = rx0(tx) - 10 * n * log (d/d0)
    */
-  static Ptr<StaticMobilityModel> zero = CreateObject<StaticMobilityModel> (Vector (0.0, 0.0, 0.0));
-  static Ptr<StaticMobilityModel> reference = CreateObject<StaticMobilityModel> (Vector (m_referenceDistance, 0.0, 0.0));
+  static Ptr<StaticMobilityModel> zero = 
+    CreateObjectWith<StaticMobilityModel> ("position", 
+                                           Vector (0.0, 0.0, 0.0));
+  static Ptr<StaticMobilityModel> reference = 
+    CreateObjectWith<StaticMobilityModel> ("position", 
+                                           Vector (m_referenceDistance, 0.0, 0.0));
   double rx0 = m_reference->GetRxPower (txPowerDbm, zero, reference);
   double pathLossDb = 10 * m_exponent * log10 (distance / m_referenceDistance);
   double rxPowerDbm = rx0 - pathLossDb;
--- a/src/devices/wifi/wifi-net-device.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -159,14 +159,12 @@
  ***************************************************************/
 
 
-WifiNetDevice::WifiNetDevice (Ptr<Node> node)
-  : NetDevice (node, Mac48Address::Allocate ())
-{
-  Construct ();
-}
 
 WifiNetDevice::WifiNetDevice (Ptr<Node> node, Mac48Address self)
-  : NetDevice (node, self)
+  : m_node (node),
+    m_address (self),
+    m_name (""),
+    m_linkUp (false)
 {
   Construct ();
 }
@@ -177,9 +175,7 @@
 void
 WifiNetDevice::Construct (void)
 {
-  SetMtu (2300);
-  EnableBroadcast (Mac48Address ("ff:ff:ff:ff:ff:ff"));
-
+  m_mtu = 2300;
   // the physical layer.
   m_phy = Create<WifiPhy> (this);
 
@@ -313,21 +309,6 @@
   m_phy->SetChannel (channel);
   NotifyAttached ();
 }
-bool
-WifiNetDevice::SendTo (Ptr<Packet> packet, const Address &to, uint16_t protocolNumber)
-{
-  NS_ASSERT (Mac48Address::IsMatchingType (to));
-
-  Mac48Address realTo = Mac48Address::ConvertFrom (to);
-
-  LlcSnapHeader llc;
-  llc.SetType (protocolNumber);
-  packet->AddHeader (llc);
-
-  m_txLogger (packet, realTo);
-
-  return DoSendTo (packet, realTo);
-}
 void 
 WifiNetDevice::DoForwardUp (Ptr<Packet> packet, const Mac48Address &from)
 {
@@ -335,7 +316,7 @@
 
   LlcSnapHeader llc;
   packet->RemoveHeader (llc);
-  NetDevice::ForwardUp (packet, llc.GetType (), from);
+  m_rxCallback (this, packet, llc.GetType (), from);
 }
 Mac48Address 
 WifiNetDevice::GetSelfAddress (void) const
@@ -344,22 +325,11 @@
   Mac48Address self = Mac48Address::ConvertFrom (GetAddress ());
   return self;
 }
-bool 
-WifiNetDevice::DoNeedsArp (void) const
-{
-  return true;
-}
-Ptr<Channel> 
-WifiNetDevice::DoGetChannel (void) const
-{
-  return m_channel;
-}
 void 
 WifiNetDevice::DoDispose (void)
 {
-  // chain up.
-  NetDevice::DoDispose ();
   // cleanup local
+  m_node = 0;
   m_channel = 0;
   delete m_stations;
   delete m_rxMiddle;
@@ -374,6 +344,136 @@
   m_rxMiddle = 0;
   m_txMiddle = 0;
   m_parameters = 0;
+  // chain up.
+  NetDevice::DoDispose ();
+}
+
+void
+WifiNetDevice::NotifyLinkUp (void)
+{
+  m_linkUp = true;
+  if (!m_linkChangeCallback.IsNull ())
+    {
+      m_linkChangeCallback ();
+    }
+}
+void
+WifiNetDevice::NotifyLinkDown (void)
+{
+  m_linkUp = false;
+  m_linkChangeCallback ();
+}
+
+void 
+WifiNetDevice::SetName(const std::string name)
+{
+  m_name = name;
+}
+std::string 
+WifiNetDevice::GetName(void) const
+{
+  return m_name;
+}
+void 
+WifiNetDevice::SetIfIndex(const uint32_t index)
+{
+  m_ifIndex = index;
+}
+uint32_t 
+WifiNetDevice::GetIfIndex(void) const
+{
+  return m_ifIndex;
+}
+Ptr<Channel> 
+WifiNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+Address 
+WifiNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+bool 
+WifiNetDevice::SetMtu (const uint16_t mtu)
+{
+  m_mtu = mtu;
+  return true;
+}
+uint16_t 
+WifiNetDevice::GetMtu (void) const
+{
+  return m_mtu;
+}
+bool 
+WifiNetDevice::IsLinkUp (void) const
+{
+  return m_linkUp;
+}
+void 
+WifiNetDevice::SetLinkChangeCallback (Callback<void> callback)
+{
+  m_linkChangeCallback = callback;
+}
+bool 
+WifiNetDevice::IsBroadcast (void) const
+{
+  return true;
+}
+Address
+WifiNetDevice::GetBroadcast (void) const
+{
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+bool 
+WifiNetDevice::IsMulticast (void) const
+{
+  return false;
+}
+Address 
+WifiNetDevice::GetMulticast (void) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+Address 
+WifiNetDevice::MakeMulticastAddress (Ipv4Address multicastGroup) const
+{
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+bool 
+WifiNetDevice::IsPointToPoint (void) const
+{
+  return false;
+}
+bool 
+WifiNetDevice::Send(Ptr<Packet> packet, const Address& to, uint16_t protocolNumber)
+{
+  NS_ASSERT (Mac48Address::IsMatchingType (to));
+
+  Mac48Address realTo = Mac48Address::ConvertFrom (to);
+
+  LlcSnapHeader llc;
+  llc.SetType (protocolNumber);
+  packet->AddHeader (llc);
+
+  m_txLogger (packet, realTo);
+
+  return DoSendTo (packet, realTo);
+}
+Ptr<Node> 
+WifiNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+bool 
+WifiNetDevice::NeedsArp (void) const
+{
+  return true;
+}
+void 
+WifiNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
 }
 
 
@@ -381,11 +481,6 @@
  *            Adhoc code
  *****************************************************/
 
-AdhocWifiNetDevice::AdhocWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 AdhocWifiNetDevice::AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
@@ -462,11 +557,6 @@
  *            STA code
  *****************************************************/
 
-NqstaWifiNetDevice::NqstaWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 NqstaWifiNetDevice::NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
@@ -526,13 +616,13 @@
 void 
 NqstaWifiNetDevice::Associated (void)
 {
-  NetDevice::NotifyLinkUp ();
+  WifiNetDevice::NotifyLinkUp ();
 }
 
 void 
 NqstaWifiNetDevice::DisAssociated (void)
 {
-  NetDevice::NotifyLinkDown ();
+  WifiNetDevice::NotifyLinkDown ();
 }
 void 
 NqstaWifiNetDevice::DoDispose (void)
@@ -560,11 +650,6 @@
  *****************************************************/
 
 
-NqapWifiNetDevice::NqapWifiNetDevice (Ptr<Node> node)
-  : WifiNetDevice (node)
-{
-  DoConstruct ();
-}
 NqapWifiNetDevice::NqapWifiNetDevice (Ptr<Node> node, Mac48Address self)
   : WifiNetDevice (node, self)
 {
--- a/src/devices/wifi/wifi-net-device.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/wifi/wifi-net-device.h	Wed Feb 27 22:19:39 2008 +0100
@@ -98,14 +98,32 @@
    */
   virtual Ssid GetSsid (void) const = 0;
 
+  // inherited from NetDevice base class.
+  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 Ptr<Node> GetNode (void) const;
+  virtual bool NeedsArp (void) const;
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
 private:
   class PhyListener;
   class NavListener;
 
-  // inherited from NetDevice
-  virtual bool DoNeedsArp (void) const;
-  virtual Ptr<Channel> DoGetChannel (void) const;
-  virtual bool SendTo (Ptr<Packet> packet, const Address &to, uint16_t protocolNumber);
   // defined for children
   virtual void NotifyAttached (void) = 0;
   virtual bool DoSendTo (Ptr<const Packet> packet, const Mac48Address &to) = 0;
@@ -115,14 +133,15 @@
   CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_rxLogger;
   CallbackTraceSource<Ptr<const Packet>, Mac48Address> m_txLogger;
 protected:
-  // inherited from Object
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
-  WifiNetDevice (Ptr<Node> node);
   WifiNetDevice (Ptr<Node> node, Mac48Address self);
   void DoForwardUp (Ptr<Packet> packet, const Mac48Address &from);
   Ptr<DcaTxop> CreateDca (uint32_t minCw, uint32_t maxCw, uint32_t aifsn) const;
+  void NotifyLinkUp (void);
+  void NotifyLinkDown (void);
   // inherited from Object
   virtual void DoDispose (void);
+  // inherited from Object
+  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
 
   Ptr<WifiChannel> m_channel;
   Ptr<WifiPhy> m_phy;
@@ -134,6 +153,15 @@
   DcfManager *m_manager;
   PhyListener *m_phyListener;
   NavListener *m_navListener;
+
+  Ptr<Node> m_node;
+  Mac48Address m_address;
+  NetDevice::ReceiveCallback m_rxCallback;
+  uint32_t m_ifIndex;
+  std::string m_name;
+  bool m_linkUp;
+  Callback<void> m_linkChangeCallback;
+  uint16_t m_mtu;
 };
 
 /**
@@ -144,7 +172,6 @@
  */
 class AdhocWifiNetDevice : public WifiNetDevice {
 public:
-  AdhocWifiNetDevice (Ptr<Node> node);
   AdhocWifiNetDevice (Ptr<Node> node, Mac48Address self);
   virtual ~AdhocWifiNetDevice ();
 
@@ -184,7 +211,6 @@
   /**
    * The ssid is initialized from \valueref{WifiSsid}.
    */
-  NqstaWifiNetDevice (Ptr<Node> node);
   NqstaWifiNetDevice (Ptr<Node> node, Mac48Address self);
   virtual ~NqstaWifiNetDevice ();
 
--- a/src/devices/wifi/wifi-phy.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/devices/wifi/wifi-phy.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -30,6 +30,7 @@
 #include "ns3/assert.h"
 #include "ns3/log.h"
 #include "ns3/composite-trace-resolver.h"
+#include "ns3/object-base.h"
 #include <math.h>
 
 NS_LOG_COMPONENT_DEFINE ("WifiPhy");
@@ -76,7 +77,8 @@
  *       Phy event class
  ****************************************************************/
 
-class RxEvent {
+class RxEvent : public ObjectBase 
+{
 public:
   RxEvent (uint32_t size, WifiMode payloadMode, 
            enum WifiPreamble preamble,
--- a/src/internet-node/arp-l3-protocol.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/arp-l3-protocol.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -41,12 +41,17 @@
 ArpL3Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ArpL3Protocol")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("Node", "The node to which this protocol is associated.",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&ArpL3Protocol::m_node),
+                   MakePtrChecker<Node> ())
+    ;
   return tid;
 }
 
-ArpL3Protocol::ArpL3Protocol (Ptr<Node> node)
-  : m_node (node)
+ArpL3Protocol::ArpL3Protocol ()
 {
   NS_LOG_FUNCTION;
 }
--- a/src/internet-node/arp-l3-protocol.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/arp-l3-protocol.h	Wed Feb 27 22:19:39 2008 +0100
@@ -46,7 +46,7 @@
    * \brief Constructor
    * \param node The node which this ARP object is associated with
    */
-  ArpL3Protocol (Ptr<Node> node);
+  ArpL3Protocol ();
   virtual ~ArpL3Protocol ();
   /**
    * \brief Recieve a packet
--- a/src/internet-node/internet-node.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/internet-node.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -21,7 +21,6 @@
 // Implementation of the InternetNode class for ns3.
 // George F. Riley, Georgia Tech, Fall 2006
 
-#include "ns3/composite-trace-resolver.h"
 #include "ns3/net-device.h"
 #include "ns3/callback.h"
 
@@ -53,8 +52,8 @@
 void
 InternetNode::Construct (void)
 {
-  Ptr<Ipv4L3Protocol> ipv4 = CreateObject<Ipv4L3Protocol> (this);
-  Ptr<ArpL3Protocol> arp = CreateObject<ArpL3Protocol> (this);
+  Ptr<Ipv4L3Protocol> ipv4 = CreateObjectWith<Ipv4L3Protocol> ("Node", Ptr<Node> (this));
+  Ptr<ArpL3Protocol> arp = CreateObjectWith<ArpL3Protocol> ("Node", Ptr<Node> (this));
   // XXX remove the PeekPointer below.
   RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, PeekPointer (ipv4)), 
                            Ipv4L3Protocol::PROT_NUMBER, 0);
@@ -62,9 +61,9 @@
                            ArpL3Protocol::PROT_NUMBER, 0);
 
 
-  Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObject<Ipv4L4Demux> (this);
-  Ptr<UdpL4Protocol> udp = CreateObject<UdpL4Protocol> (this);
-  Ptr<TcpL4Protocol> tcp = CreateObject<TcpL4Protocol> (this);
+  Ptr<Ipv4L4Demux> ipv4L4Demux = CreateObjectWith<Ipv4L4Demux> ("Node", Ptr<Node> (this));
+  Ptr<UdpL4Protocol> udp = CreateObjectWith<UdpL4Protocol> ("Node", Ptr<Node> (this));
+  Ptr<TcpL4Protocol> tcp = CreateObjectWith<TcpL4Protocol> ("Node", Ptr<Node> (this));
 
   ipv4L4Demux->Insert (udp);
   ipv4L4Demux->Insert (tcp);
@@ -81,16 +80,6 @@
   Object::AggregateObject (ipv4L4Demux);
 }
 
-Ptr<TraceResolver>
-InternetNode::GetTraceResolver () const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  Ptr<Ipv4L3Protocol> ipv4 = GetObject<Ipv4L3Protocol> ();
-  resolver->AddComposite ("ipv4", ipv4);
-  resolver->SetParentResolver (Node::GetTraceResolver ());
-  return resolver;
-}
-
 void 
 InternetNode::DoDispose()
 {
--- a/src/internet-node/internet-node.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/internet-node.h	Wed Feb 27 22:19:39 2008 +0100
@@ -63,7 +63,6 @@
 
 protected:
   virtual void DoDispose(void);
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
 private:
   void Construct (void);
 };
--- a/src/internet-node/ipv4-l3-protocol.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l3-protocol.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -21,12 +21,14 @@
 
 #include "ns3/packet.h"
 #include "ns3/log.h"
-#include "ns3/composite-trace-resolver.h"
 #include "ns3/callback.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/ipv4-route.h"
 #include "ns3/node.h"
 #include "ns3/net-device.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/object-vector.h"
 
 #include "ipv4-l3-protocol.h"
 #include "ipv4-l4-protocol.h"
@@ -48,123 +50,34 @@
 Ipv4L3Protocol::GetTypeId (void)
 {
   static TypeId tid = TypeId ("Ipv4L3Protocol")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddConstructor<Ipv4L3Protocol> ()
+    .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
+                   Uinteger (64),
+                   MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("Node", "The node to which this l3 protocol is attached.",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&Ipv4L3Protocol::m_node),
+                   MakePtrChecker<Node> ())
+    .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
+                   MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
+    .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
+                     MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
+    .AddTraceSource ("Drop", "Drop ipv4 packet",
+                     MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
+    .AddAttribute ("Interfaces", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
+                   ObjectVector (),
+                   MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
+                   MakeObjectVectorChecker ())
+    ;
   return tid;
 }
 
-Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement ()
-  : m_type (TX)
-{
-  NS_LOG_FUNCTION;
-}
-
-Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement (enum Type type)
-  : m_type (type)
-{
-  NS_LOG_FUNCTION;
-}
-
-bool 
-Ipv4L3ProtocolTraceContextElement::IsTx (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_type == TX;
-}
-
-bool 
-Ipv4L3ProtocolTraceContextElement::IsRx (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_type == RX;
-}
-
-bool 
-Ipv4L3ProtocolTraceContextElement::IsDrop (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_type == DROP;
-}
-
-void 
-Ipv4L3ProtocolTraceContextElement::Print (std::ostream &os) const
-{
-  NS_LOG_FUNCTION;
-  os << "ipv4=";
-  switch (m_type)
-    {
-    case TX:
-      os << "tx";
-      break;
-    case RX:
-      os << "rx";
-      break;
-    case DROP:
-      os << "drop";
-      break;
-    }
-}
-
-uint16_t 
-Ipv4L3ProtocolTraceContextElement::GetUid (void)
-{
-  NS_LOG_FUNCTION;
-  static uint16_t uid = AllocateUid<Ipv4L3ProtocolTraceContextElement> ("Ipv4L3ProtocolTraceContextElement");
-  return uid;
-}
-
-std::string 
-Ipv4L3ProtocolTraceContextElement::GetTypeName (void) const
-{
-  NS_LOG_FUNCTION;
-  return "ns3::Ipv4L3ProtocolTraceContextElement";
-}
-
-Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex ()
-  : m_index (0)
-{
-  NS_LOG_FUNCTION;
-}
-
-Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex (uint32_t index)
-  : m_index (index)
-{
-  NS_LOG_FUNCTION;
-}
-
-uint32_t 
-Ipv4L3ProtocolInterfaceIndex::Get (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_index;
-}
-
-void 
-Ipv4L3ProtocolInterfaceIndex::Print (std::ostream &os) const
-{
-  os << "ipv4-interface=" << m_index;
-}
-
-uint16_t 
-Ipv4L3ProtocolInterfaceIndex::GetUid (void)
-{
-  NS_LOG_FUNCTION;
-  static uint16_t uid = AllocateUid<Ipv4L3ProtocolInterfaceIndex> ("Ipv4L3ProtocolInterfaceIndex");
-  return uid;
-}
-
-std::string
-Ipv4L3ProtocolInterfaceIndex::GetTypeName (void) const
-{
-  NS_LOG_FUNCTION;
-  return "ns3::Ipv4L3ProtocolInterfaceIndex";
-}
-
-
-Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
+Ipv4L3Protocol::Ipv4L3Protocol()
   : m_nInterfaces (0),
-    m_defaultTtl (64),
-    m_identification (0),
-    m_node (node)
+    m_identification (0)
 {
   NS_LOG_FUNCTION;
   m_staticRouting = CreateObject<Ipv4StaticRouting> ();
@@ -201,32 +114,6 @@
   interface->SetUp ();
 }
 
-Ptr<TraceResolver>
-Ipv4L3Protocol::GetTraceResolver (void) const
-{
-  NS_LOG_FUNCTION;
-
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddSource ("tx", 
-                       TraceDoc ("send ipv4 packet to outgoing interface",
-                                 "Ptr<const Packet>", "packet sent",
-                                 "uint32_t", "index of output ipv4 interface"),
-                       m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX));
-  resolver->AddSource ("rx",
-                       TraceDoc ("receive ipv4 packet from incoming interface",
-                                 "Ptr<const Packet>", "packet received",
-                                 "uint32_t", "index of input ipv4 interface"),
-                       m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX));
-  resolver->AddSource ("drop", 
-                       TraceDoc ("drop ipv4 packet",
-                                 "Ptr<const Packet>", "packet dropped"),
-                       m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP));
-  resolver->AddArray ("interfaces", 
-                      m_interfaces.begin (), m_interfaces.end (), 
-                      Ipv4L3ProtocolInterfaceIndex ());
-  return resolver;
-}
-
 void 
 Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
 {
--- a/src/internet-node/ipv4-l3-protocol.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l3-protocol.h	Wed Feb 27 22:19:39 2008 +0100
@@ -24,11 +24,10 @@
 
 #include <list>
 #include <stdint.h>
-#include "ns3/callback-trace-source.h"
-#include "ns3/trace-context-element.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4.h"
+#include "ns3/traced-callback.h"
 #include "ipv4-header.h"
 #include "ipv4-static-routing.h"
 
@@ -41,59 +40,6 @@
 class Ipv4Header;
 class Ipv4Route;
 class Node;
-class TraceResolver;
-class TraceContext;
-
-/**
- * \brief hold in a TraceContext the type of trace source used by this Ipv4L3Protocol
- */
-class Ipv4L3ProtocolTraceContextElement : public TraceContextElement
-{
-public:
-  enum Type {
-    TX,
-    RX,
-    DROP,
-  };
-  Ipv4L3ProtocolTraceContextElement ();
-  Ipv4L3ProtocolTraceContextElement (enum Type type);
-  /**
-   * \returns true if this is a tx event, false otherwise.
-   */
-  bool IsTx (void) const;
-  /**
-   * \returns true if this is a rx event, false otherwise.
-   */
-  bool IsRx (void) const;
-  /**
-   * \returns true if this is a drop event, false otherwise.
-   */
-  bool IsDrop (void) const;
-  void Print (std::ostream &os) const;
-  static uint16_t GetUid (void);
-  std::string GetTypeName (void) const;
-private:
-  enum Type m_type;
-};
-
-/**
- * \brief hold in a TraceContext the index of an Ipv4Interface within the ipv4 stack of a Node
- */
-class Ipv4L3ProtocolInterfaceIndex : public TraceContextElement
-{
-public:
-  Ipv4L3ProtocolInterfaceIndex ();
-  Ipv4L3ProtocolInterfaceIndex (uint32_t index);
-  /**
-   * \returns the index of the Ipv4Interface within a Node.
-   */
-  uint32_t Get (void) const;
-  void Print (std::ostream &os) const;
-  static uint16_t GetUid (void);
-  std::string GetTypeName (void) const;
-private:
-  uint32_t m_index;
-};
 
 
 class Ipv4L3Protocol : public Object
@@ -102,7 +48,7 @@
   static TypeId GetTypeId (void);
   static const uint16_t PROT_NUMBER;
 
-  Ipv4L3Protocol(Ptr<Node> node);
+  Ipv4L3Protocol();
   virtual ~Ipv4L3Protocol ();
 
   /**
@@ -213,7 +159,6 @@
 protected:
 
   virtual void DoDispose (void);
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
 
 private:
   void Lookup (uint32_t ifIndex,
@@ -243,9 +188,9 @@
   uint8_t m_defaultTtl;
   uint16_t m_identification;
   Ptr<Node> m_node;
-  CallbackTraceSource<Ptr<const Packet>, uint32_t> m_txTrace;
-  CallbackTraceSource<Ptr<const Packet>, uint32_t> m_rxTrace;
-  CallbackTraceSource<Ptr<const Packet> > m_dropTrace;
+  TracedCallback<Ptr<const Packet>, uint32_t> m_txTrace;
+  TracedCallback<Ptr<const Packet>, uint32_t> m_rxTrace;
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
 
   Ipv4RoutingProtocolList m_routingProtocols;
 
--- a/src/internet-node/ipv4-l4-demux.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l4-demux.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,8 +23,8 @@
 // George F. Riley, Georgia Tech, Fall 2006
 
 #include <sstream>
-#include "ns3/composite-trace-resolver.h"
 #include "ns3/node.h"
+#include "ns3/object-vector.h"
 #include "ipv4-l4-demux.h"
 #include "ipv4-l4-protocol.h"
 
@@ -32,44 +32,24 @@
 
 NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Demux);
 
-Ipv4L4ProtocolTraceContextElement::Ipv4L4ProtocolTraceContextElement ()
-  : m_protocolNumber (0)
-{}
-Ipv4L4ProtocolTraceContextElement::Ipv4L4ProtocolTraceContextElement (int protocolNumber)
-  : m_protocolNumber (protocolNumber)
-{}
-int 
-Ipv4L4ProtocolTraceContextElement::Get (void) const
-{
-  return m_protocolNumber;
-}
-void 
-Ipv4L4ProtocolTraceContextElement::Print (std::ostream &os) const
-{
-  os << "ipv4-protocol=0x" << std::hex << m_protocolNumber << std::dec;
-}
-uint16_t 
-Ipv4L4ProtocolTraceContextElement::GetUid (void)
-{
-  static uint16_t uid = AllocateUid<Ipv4L4ProtocolTraceContextElement> ("Ipv4L4ProtocolTraceContextElement");
-  return uid;
-}
-std::string 
-Ipv4L4ProtocolTraceContextElement::GetTypeName (void) const
-{
-  return "ns3::Ipv4L4ProtocolTraceContextElement";
-}
-
 TypeId 
 Ipv4L4Demux::GetTypeId (void)
 {
   static TypeId tid = TypeId ("Ipv4L4Demux")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("Node", "The node to which this object is associated.",
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&Ipv4L4Demux::m_node),
+                   MakePtrChecker<Node> ())
+    .AddAttribute ("Protocols", "The set of protocols registered with this demux.",
+                   ObjectVector (),
+                   MakeObjectVectorAccessor (&Ipv4L4Demux::m_protocols),
+                   MakeObjectVectorChecker ())
+    ;
   return tid;
 }
 
-Ipv4L4Demux::Ipv4L4Demux (Ptr<Node> node)
-  : m_node (node)
+Ipv4L4Demux::Ipv4L4Demux ()
 {}
 
 Ipv4L4Demux::~Ipv4L4Demux()
@@ -88,21 +68,6 @@
   Object::DoDispose ();
 }
 
-Ptr<TraceResolver>
-Ipv4L4Demux::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
-    {
-      Ptr<Ipv4L4Protocol> protocol = *i;
-      std::ostringstream oss;
-      oss << (unsigned int) (*i)->GetProtocolNumber ();
-      Ipv4L4ProtocolTraceContextElement protocolNumber = (*i)->GetProtocolNumber ();
-      resolver->AddComposite (oss.str (), protocol, protocolNumber);
-    }
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
-}
 void
 Ipv4L4Demux::Insert(Ptr<Ipv4L4Protocol> protocol)
 {
--- a/src/internet-node/ipv4-l4-demux.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l4-demux.h	Wed Feb 27 22:19:39 2008 +0100
@@ -28,42 +28,21 @@
 #include <list>
 #include "ns3/object.h"
 #include "ns3/ptr.h"
-#include "ns3/trace-context-element.h"
 
 namespace ns3 {
 
 class Ipv4L4Protocol;
 class Node;
-class TraceResolver;
 class TraceContext;
 
 /**
- * \brief hold in a TraceContext the protocol number of a L4 Protocol
- */
-class Ipv4L4ProtocolTraceContextElement : public TraceContextElement
-{
-public:
-  Ipv4L4ProtocolTraceContextElement ();
-  Ipv4L4ProtocolTraceContextElement (int protocolNumber);
-  /**
-   * \returns the protocol number as registered in the Ipv4L4Demux.
-   */
-  int Get (void) const;
-  void Print (std::ostream &os) const;
-  static uint16_t GetUid (void);
-  std::string GetTypeName (void) const;
-private:
-  int m_protocolNumber;
-};
-
-/**
  * \brief L4 Ipv4 Demux
  */
 class Ipv4L4Demux : public Object
 {
 public:
   static TypeId GetTypeId (void);
-  Ipv4L4Demux (Ptr<Node> node);
+  Ipv4L4Demux ();
   virtual ~Ipv4L4Demux();
 
   /**
@@ -95,7 +74,6 @@
    */
   void Remove (Ptr<Ipv4L4Protocol> protocol);
 protected:
-  Ptr<TraceResolver> GetTraceResolver (void) const;
   virtual void DoDispose (void);
 private:
   typedef std::list<Ptr<Ipv4L4Protocol> > L4List_t;
--- a/src/internet-node/ipv4-l4-protocol.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l4-protocol.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,32 +23,30 @@
 // George F. Riley, Georgia Tech, Spring 2007
 
 #include "ipv4-l4-protocol.h"
+#include "ns3/uinteger.h"
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (Ipv4L4Protocol);
 
-Ipv4L4Protocol::Ipv4L4Protocol(int protocolNumber, int version)
-  : m_protocolNumber (protocolNumber),
-    m_version (version)
-{}
+TypeId 
+Ipv4L4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("Ipv4L4Protocol")
+    .SetParent<Object> ()
+    .AddAttribute ("ProtocolNumber", "The Ipv4 protocol number.",
+                   Uinteger (0),
+                   MakeUintegerAccessor (&Ipv4L4Protocol::GetProtocolNumber),
+                   MakeUintegerChecker<int> ())
+    .AddAttribute ("Version", "The version of the protocol.",
+                   Uinteger (0),
+                   MakeUintegerAccessor (&Ipv4L4Protocol::GetVersion),
+                   MakeUintegerChecker<int> ())
+    ;
+  return tid;
+}
+
 Ipv4L4Protocol::~Ipv4L4Protocol ()
 {}
 
-int 
-Ipv4L4Protocol::GetProtocolNumber (void) const
-{
-  return m_protocolNumber;
-}
-int 
-Ipv4L4Protocol::GetVersion() const
-{
-  return m_version;
-}
-
-void 
-Ipv4L4Protocol::DoDispose (void)
-{
-  Object::DoDispose ();
-}
-
 }//namespace ns3
--- a/src/internet-node/ipv4-l4-protocol.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/ipv4-l4-protocol.h	Wed Feb 27 22:19:39 2008 +0100
@@ -44,17 +44,18 @@
 class Ipv4L4Protocol : public Object
 {
 public:
-  Ipv4L4Protocol(int protocolNumber, int version);
+  static TypeId GetTypeId (void);
+
   virtual ~Ipv4L4Protocol ();
 
   /**
    * \returns the protocol number of this protocol.
    */
-  int GetProtocolNumber (void) const;
+  virtual int GetProtocolNumber (void) const = 0;
   /**
    * \returns the version number of this protocol.
    */
-  int GetVersion() const;
+  virtual int GetVersion (void) const = 0;
 
   /**
    * \param p packet to forward up
@@ -69,11 +70,6 @@
                        Ipv4Address const &source,
                        Ipv4Address const &destination,
                        Ptr<Ipv4Interface> incomingInterface) = 0;
-protected:
-  virtual void DoDispose (void);
-private:
-  int m_protocolNumber;
-  int m_version;
 };
 
 } // Namespace ns3
--- a/src/internet-node/tcp-l4-protocol.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/tcp-l4-protocol.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -41,6 +41,8 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (TcpL4Protocol);
+
 //State Machine things --------------------------------------------------------
 TcpStateMachine::TcpStateMachine() 
   : aT (LAST_STATE, StateActionVec_t(LAST_EVENT)),
@@ -309,20 +311,42 @@
 /* see http://www.iana.org/assignments/protocol-numbers */
 const uint8_t TcpL4Protocol::PROT_NUMBER = 6;
 
-TcpL4Protocol::TcpL4Protocol (Ptr<Node> node)
-  : Ipv4L4Protocol (PROT_NUMBER, 2),
-    m_node (node),
-    m_endPoints (new Ipv4EndPointDemux ())
+TypeId 
+TcpL4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("TcpL4Protocol")
+    .SetParent<Ipv4L4Protocol> ()
+    .AddAttribute ("Node", "The node to which this protocol is associated",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&TcpL4Protocol::m_node),
+                   MakePtrChecker<Node> ())
+    ;
+  return tid;
+}
+
+TcpL4Protocol::TcpL4Protocol ()
+  : m_endPoints (new Ipv4EndPointDemux ())
 {
   NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << node);
   NS_LOG_LOGIC("Made a TcpL4Protocol "<<this);
 }
 
 TcpL4Protocol::~TcpL4Protocol ()
 {
   NS_LOG_FUNCTION;
- }
+}
+
+int 
+TcpL4Protocol::GetProtocolNumber (void) const
+{
+  return PROT_NUMBER;
+}
+int 
+TcpL4Protocol::GetVersion (void) const
+{
+  return 2;
+}
 
 void
 TcpL4Protocol::DoDispose (void)
--- a/src/internet-node/tcp-l4-protocol.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/tcp-l4-protocol.h	Wed Feb 27 22:19:39 2008 +0100
@@ -45,14 +45,17 @@
  */
 class TcpL4Protocol : public Ipv4L4Protocol {
 public:
+  static TypeId GetTypeId (void);
   static const uint8_t PROT_NUMBER;
   /**
    * \brief Constructor
-   * \param node The node this protocol is associated with
    */
-  TcpL4Protocol (Ptr<Node> node);
+  TcpL4Protocol ();
   virtual ~TcpL4Protocol ();
 
+  virtual int GetProtocolNumber (void) const;
+  virtual int GetVersion (void) const;
+
   /**
    * \return A smart Socket pointer to a TcpSocket, allocated by this instance
    * of the TCP protocol
--- a/src/internet-node/udp-l4-protocol.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/udp-l4-protocol.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -35,13 +35,28 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (UdpL4Protocol);
+
 /* see http://www.iana.org/assignments/protocol-numbers */
 const uint8_t UdpL4Protocol::PROT_NUMBER = 17;
 
-UdpL4Protocol::UdpL4Protocol (Ptr<Node> node)
-  : Ipv4L4Protocol (PROT_NUMBER, 2),
-    m_node (node),
-    m_endPoints (new Ipv4EndPointDemux ())
+TypeId 
+UdpL4Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("UdpL4Protocol")
+    .SetParent<Ipv4L4Protocol> ()
+    .AddConstructor<UdpL4Protocol> ()
+    .AddAttribute ("Node", "The node which contains this protocol.",
+                   TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT,
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&UdpL4Protocol::m_node),
+                   MakePtrChecker<Node> ())
+    ;
+  return tid;
+}
+
+UdpL4Protocol::UdpL4Protocol ()
+  : m_endPoints (new Ipv4EndPointDemux ())
 {
   NS_LOG_FUNCTION;
 }
@@ -51,6 +66,18 @@
   NS_LOG_FUNCTION;
 }
 
+int 
+UdpL4Protocol::GetProtocolNumber (void) const
+{
+  return PROT_NUMBER;
+}
+int 
+UdpL4Protocol::GetVersion (void) const
+{
+  return 2;
+}
+
+
 void
 UdpL4Protocol::DoDispose (void)
 {
--- a/src/internet-node/udp-l4-protocol.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/udp-l4-protocol.h	Wed Feb 27 22:19:39 2008 +0100
@@ -41,14 +41,18 @@
  */
 class UdpL4Protocol : public Ipv4L4Protocol {
 public:
+  static TypeId GetTypeId (void);
   static const uint8_t PROT_NUMBER;
   /**
    * \brief Constructor
    * \param node The node this protocol is associated with
    */
-  UdpL4Protocol (Ptr<Node> node);
+  UdpL4Protocol ();
   virtual ~UdpL4Protocol ();
 
+  virtual int GetProtocolNumber (void) const;
+  virtual int GetVersion (void) const;
+
   /**
    * \return A smart Socket pointer to a UdpSocket, allocated by this instance
    * of the UDP protocol
--- a/src/internet-node/udp-socket.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/internet-node/udp-socket.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -400,7 +400,8 @@
   Ptr<Node> rxNode = CreateObject<InternetNode> ();
   Ptr<PointToPointNetDevice> rxDev1, rxDev2;
   { // first interface
-    rxDev1 = CreateObject<PointToPointNetDevice> (rxNode);
+    rxDev1 = CreateObjectWith<PointToPointNetDevice> ("Node", rxNode, "Address", Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev1);
     rxDev1->AddQueue(CreateObject<DropTailQueue> ());
     Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
     uint32_t netdev_idx = ipv4->AddInterface (rxDev1);
@@ -410,7 +411,8 @@
   }
 
   { // second interface
-    rxDev2 = CreateObject<PointToPointNetDevice> (rxNode);
+    rxDev2 = CreateObjectWith<PointToPointNetDevice> ("Node", rxNode, "Address", Mac48Address::Allocate ());
+    rxNode->AddDevice (rxDev2);
     rxDev2->AddQueue(CreateObject<DropTailQueue> ());
     Ptr<Ipv4> ipv4 = rxNode->GetObject<Ipv4> ();
     uint32_t netdev_idx = ipv4->AddInterface (rxDev2);
@@ -423,7 +425,7 @@
   Ptr<Node> txNode = CreateObject<InternetNode> ();
   Ptr<PointToPointNetDevice> txDev;
   {
-    txDev = CreateObject<PointToPointNetDevice> (txNode);
+    txDev = CreateObjectWith<PointToPointNetDevice> ("Node", txNode, "Address", Mac48Address::Allocate ());
     txDev->AddQueue(CreateObject<DropTailQueue> ());
     Ptr<Ipv4> ipv4 = txNode->GetObject<Ipv4> ();
     uint32_t netdev_idx = ipv4->AddInterface (txDev);
--- a/src/mobility/hierarchical-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/hierarchical-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -28,32 +28,52 @@
 HierarchicalMobilityModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("HierarchicalMobilityModel")
-    .SetParent<MobilityModel> ();
+    .SetParent<MobilityModel> ()
+    .AddConstructor<HierarchicalMobilityModel> ()
+    .AddAttribute ("child", "The child mobility model.",
+                   Ptr<MobilityModel> (0),
+                   MakePtrAccessor (&HierarchicalMobilityModel::SetChild),
+                   MakePtrChecker<MobilityModel> ())
+    .AddAttribute ("parent", "The parent mobility model.",
+                   Ptr<MobilityModel> (0),
+                   MakePtrAccessor (&HierarchicalMobilityModel::SetParent),
+                   MakePtrChecker<MobilityModel> ())
+    ;
   return tid;
 }
 
-HierarchicalMobilityModel::HierarchicalMobilityModel (Ptr<MobilityModel> child, Ptr<MobilityModel> parent)
-  : m_child (child),
-    m_parent (parent)
+HierarchicalMobilityModel::HierarchicalMobilityModel ()
+{}
+
+void 
+HierarchicalMobilityModel::SetChild (Ptr<MobilityModel> model)
 {
-  Ptr<MobilityModelNotifier> childNotifier = 
+  m_child = model;
+  Ptr<MobilityModelNotifier> notifier = 
     m_child->GetObject<MobilityModelNotifier> ();
-  Ptr<MobilityModelNotifier> parentNotifier = 
-    m_parent->GetObject<MobilityModelNotifier> ();
-  if (childNotifier == 0)
+  if (notifier == 0)
     {
-      childNotifier = CreateObject<MobilityModelNotifier> ();
-      child->AggregateObject (childNotifier);
+      notifier = CreateObject<MobilityModelNotifier> ();
+      m_child->AggregateObject (notifier);
     }
-  if (parentNotifier == 0)
+  notifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
+}
+
+void 
+HierarchicalMobilityModel::SetParent (Ptr<MobilityModel> model)
+{
+  m_parent = model;
+  Ptr<MobilityModelNotifier> notifier = 
+    m_parent->GetObject<MobilityModelNotifier> ();
+  if (notifier == 0)
     {
-      parentNotifier = CreateObject<MobilityModelNotifier> ();
-      parent->AggregateObject (parentNotifier);
+      notifier = CreateObject<MobilityModelNotifier> ();
+      m_parent->AggregateObject (notifier);
     }
-  childNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ChildChanged, this));
-  parentNotifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
+  notifier->TraceConnect ("/course-changed", MakeCallback (&HierarchicalMobilityModel::ParentChanged, this));
 }
 
+
 Ptr<MobilityModel> 
 HierarchicalMobilityModel::GetChild (void) const
 {
--- a/src/mobility/hierarchical-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/hierarchical-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -35,11 +35,7 @@
 public:
   static TypeId GetTypeId (void);
 
-  /**
-   * \param child the "relative" mobility model
-   * \param parent the "reference" mobility model
-   */
-  HierarchicalMobilityModel (Ptr<MobilityModel> child, Ptr<MobilityModel> parent);
+  HierarchicalMobilityModel ();
 
   /**
    * \returns the child mobility model.
@@ -62,6 +58,8 @@
   virtual void DoSetPosition (const Vector &position);
   virtual Vector DoGetVelocity (void) const;
 
+  void SetChild (Ptr<MobilityModel> model);
+  void SetParent (Ptr<MobilityModel> model);
   void ParentChanged (const TraceContext &context, Ptr<const MobilityModel> model);
   void ChildChanged (const TraceContext &context, Ptr<const MobilityModel> model);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-helper.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,139 @@
+#include "mobility-helper.h"
+#include "mobility-model.h"
+#include "mobility-model-notifier.h"
+#include "position-allocator.h"
+#include "hierarchical-mobility-model.h"
+
+namespace ns3 {
+
+MobilityHelper::MobilityHelper ()
+  : m_notifierEnabled (false)
+{}
+void 
+MobilityHelper::EnableNotifier (void)
+{
+  m_notifierEnabled = true;
+}
+void 
+MobilityHelper::DisableNotifier (void)
+{
+  m_notifierEnabled = false;
+}
+void 
+MobilityHelper::SetPositionAllocator (Ptr<PositionAllocator> allocator)
+{
+  m_position = allocator;
+}
+void 
+MobilityHelper::SetPositionAllocator (std::string type,
+				      std::string n1, Attribute v1,
+				      std::string n2, Attribute v2,
+				      std::string n3, Attribute v3,
+				      std::string n4, Attribute v4,
+				      std::string n5, Attribute v5,
+				      std::string n6, Attribute v6,
+				      std::string n7, Attribute v7,
+				      std::string n8, Attribute v8,
+				      std::string n9, Attribute v9)
+{
+  ObjectFactory pos;
+  pos.SetTypeId (type);
+  pos.Set (n1, v1);
+  pos.Set (n2, v2);
+  pos.Set (n3, v3);
+  pos.Set (n4, v4);
+  pos.Set (n5, v5);
+  pos.Set (n6, v6);
+  pos.Set (n7, v7);
+  pos.Set (n8, v8);
+  pos.Set (n9, v9);
+  m_position = pos.Create ()->GetObject<PositionAllocator> ();
+}
+
+void 
+MobilityHelper::SetMobilityModel (std::string type,
+				  std::string n1, Attribute v1,
+				  std::string n2, Attribute v2,
+				  std::string n3, Attribute v3,
+				  std::string n4, Attribute v4,
+				  std::string n5, Attribute v5,
+				  std::string n6, Attribute v6,
+				  std::string n7, Attribute v7,
+				  std::string n8, Attribute v8,
+				  std::string n9, Attribute v9)
+{
+  m_mobility.SetTypeId (type);
+  m_mobility.Set (n1, v1);
+  m_mobility.Set (n2, v2);
+  m_mobility.Set (n3, v3);
+  m_mobility.Set (n4, v4);
+  m_mobility.Set (n5, v5);
+  m_mobility.Set (n6, v6);
+  m_mobility.Set (n7, v7);
+  m_mobility.Set (n8, v8);
+  m_mobility.Set (n9, v9);
+}
+
+void 
+MobilityHelper::PushReferenceMobilityModel (Ptr<Object> reference)
+{
+  Ptr<MobilityModel> mobility = reference->GetObject<MobilityModel> ();
+  m_mobilityStack.push_back (mobility);
+}
+void 
+MobilityHelper::PopReferenceMobilityModel (void)
+{
+  m_mobilityStack.pop_back ();
+}
+
+
+std::string 
+MobilityHelper::GetMobilityModelType (void) const
+{
+  return m_mobility.GetTypeId ().GetName ();
+}
+
+void 
+MobilityHelper::Layout (const std::vector<Ptr<Object> > &objects)
+{
+  for (std::vector<Ptr<Object> >::const_iterator i = objects.begin (); i != objects.end (); i++)
+    {
+      Ptr<Object> object = *i;
+      Ptr<MobilityModel> model = object->GetObject<MobilityModel> ();
+      if (model == 0)
+	{
+	  model = m_mobility.Create ()->GetObject<MobilityModel> ();
+	  if (model == 0)
+	    {
+	      NS_FATAL_ERROR ("The requested mobility model is not a mobility model: \""<< 
+			      m_mobility.GetTypeId ().GetName ()<<"\"");
+	    }
+	  if (m_mobilityStack.empty ())
+	    {
+	      object->AggregateObject (model);
+	    }
+	  else
+	    {
+	      // we need to setup a hierarchical mobility model
+	      Ptr<MobilityModel> parent = m_mobilityStack.back ();
+	      Ptr<MobilityModel> hierarchical = 
+		CreateObjectWith<HierarchicalMobilityModel> ("child", model,
+							     "parent", parent);
+	      object->AggregateObject (hierarchical);
+	    }
+	}
+      Vector position = m_position->GetNext ();
+      model->SetPosition (position);
+      if (m_notifierEnabled)
+	{
+	  Ptr<MobilityModelNotifier> notifier = 
+	    object->GetObject<MobilityModelNotifier> ();
+	  if (notifier == 0)
+	    {
+	      object->AggregateObject (CreateObject<MobilityModelNotifier> ());
+	    }
+	}
+    }
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/mobility-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,81 @@
+#ifndef MOBILITY_HELPER_H
+#define MOBILITY_HELPER_H
+
+#include <vector>
+#include "ns3/object-factory.h"
+#include "ns3/attribute.h"
+#include "position-allocator.h"
+
+namespace ns3 {
+
+class PositionAllocator;
+class MobilityModel;
+
+class MobilityHelper
+{
+public:
+  MobilityHelper ();
+
+  void EnableNotifier (void);
+  void DisableNotifier (void);
+
+  void SetPositionAllocator (Ptr<PositionAllocator> allocator);
+
+  void SetPositionAllocator (std::string type,
+			     std::string n1 = "", Attribute v1 = Attribute (),
+			     std::string n2 = "", Attribute v2 = Attribute (),
+			     std::string n3 = "", Attribute v3 = Attribute (),
+			     std::string n4 = "", Attribute v4 = Attribute (),
+			     std::string n5 = "", Attribute v5 = Attribute (),
+			     std::string n6 = "", Attribute v6 = Attribute (),
+			     std::string n7 = "", Attribute v7 = Attribute (),
+			     std::string n8 = "", Attribute v8 = Attribute (),
+			     std::string n9 = "", Attribute v9 = Attribute ());
+
+  void SetMobilityModel (std::string type,
+			 std::string n1 = "", Attribute v1 = Attribute (),
+			 std::string n2 = "", Attribute v2 = Attribute (),
+			 std::string n3 = "", Attribute v3 = Attribute (),
+			 std::string n4 = "", Attribute v4 = Attribute (),
+			 std::string n5 = "", Attribute v5 = Attribute (),
+			 std::string n6 = "", Attribute v6 = Attribute (),
+			 std::string n7 = "", Attribute v7 = Attribute (),
+			 std::string n8 = "", Attribute v8 = Attribute (),
+			 std::string n9 = "", Attribute v9 = Attribute ());
+
+  void PushReferenceMobilityModel (Ptr<Object> reference);
+  void PopReferenceMobilityModel (void);
+
+  std::string GetMobilityModelType (void) const;
+
+  template <typename T>
+  void Layout (T begin, T end);
+private:
+  void Layout (const std::vector<Ptr<Object> > &objects);
+
+  std::vector<Ptr<MobilityModel> > m_mobilityStack;
+  bool m_notifierEnabled;
+  ObjectFactory m_mobility;
+  Ptr<PositionAllocator> m_position;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void
+MobilityHelper::Layout (T begin, T end)
+{
+  std::vector<Ptr<Object> > objects;
+  for (T i = begin; i != end; i++)
+    {
+      Ptr<Object> object = *i;
+      objects.push_back (object);
+    }
+  Layout (objects);
+}
+
+} // namespace ns3
+
+#endif /* MOBILITY_HELPER_H */
--- a/src/mobility/mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -27,7 +27,19 @@
 MobilityModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("MobilityModel")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("position", "The current position of the mobility model.",
+                   TypeId::ATTR_SGC,
+                   Vector (0.0, 0.0, 0.0),
+                   MakeVectorAccessor (&MobilityModel::SetPosition,
+                                        &MobilityModel::GetPosition),
+                   MakeVectorChecker ())
+    .AddAttribute ("velocity", "The current velocity of the mobility model.",
+                   TypeId::ATTR_GET,
+                   Vector (0.0, 0.0, 0.0), // ignored initial value.
+                   MakeVectorAccessor (&MobilityModel::GetVelocity),
+                   MakeVectorChecker ())
+    ;
   return tid;
 }
 
--- a/src/mobility/ns2-mobility-file-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#include <fstream>
-#include <sstream>
-#include "ns3/log.h"
-#include "ns3/simulator.h"
-#include "ns3/node-list.h"
-#include "ns3/node.h"
-#include "ns2-mobility-file-topology.h"
-#include "static-speed-mobility-model.h"
-
-NS_LOG_COMPONENT_DEFINE ("Ns2MobilityFileTopology");
-
-namespace ns3 {
-
-
-Ns2MobilityFileTopology::Ns2MobilityFileTopology (std::string filename)
-  : m_filename (filename)
-{}
-
-
-Ptr<StaticSpeedMobilityModel>
-Ns2MobilityFileTopology::GetMobilityModel (std::string idString, const ObjectStore &store) const
-{
-  std::istringstream iss;
-  iss.str (idString);
-  uint32_t id;
-  iss >> id;
-  Ptr<Object> object = store.Get (id);
-  if (object == 0)
-    {
-      return 0;
-    }
-  Ptr<StaticSpeedMobilityModel> model = object->GetObject<StaticSpeedMobilityModel> ();
-  if (model == 0)
-    {
-      model = CreateObject<StaticSpeedMobilityModel> ();
-      object->AggregateObject (model);
-    }
-  return model;
-}
-
-double
-Ns2MobilityFileTopology::ReadDouble (std::string valueString) const
-{
-  std::istringstream iss;
-  iss.str (valueString);
-  double value;
-  iss >> value;
-  return value;
-}
-
-void 
-Ns2MobilityFileTopology::LayoutObjectStore (const ObjectStore &store) const
-{
-  std::ifstream file (m_filename.c_str (), std::ios::in);
-  if (file.is_open())
-    {
-      while (!file.eof() )
-	{
-	  std::string line;
-	  getline (file, line);
-	  std::string::size_type startNodeId = line.find_first_of ("(");
-	  std::string::size_type endNodeId = line.find_first_of (")");
-	  if (startNodeId == std::string::npos ||
-	      endNodeId == std::string::npos)
-	    {
-	      continue;
-	    }
-	  Ptr<StaticSpeedMobilityModel> model = GetMobilityModel (line.substr (startNodeId + 1, 
-									       endNodeId - startNodeId), 
-								  store);
-	  if (model == 0)
-	    {
-	      continue;
-	    }
-	  if (startNodeId == 6)
-	    {
-	      double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
-	      std::string coordinate = line.substr (endNodeId + 6, 1);
-              Vector position = model->GetPosition ();
-	      if (coordinate == "X")
-		{
-                  position.x = value;
-		  NS_LOG_DEBUG ("X=" << value);
-		}
-	      else if (coordinate == "Y")
-		{
-                  position.y = value;
-		  NS_LOG_DEBUG ("Y=" << value);
-		}
-	      else if (coordinate == "Z")
-		{
-                  position.z = value;
-		  NS_LOG_DEBUG ("Z=" << value);
-		}
-              else
-                {
-                  continue;
-                }
-              model->SetPosition (position);
-	    }
-	  else 
-	    {
-	      double at = ReadDouble (line.substr (8, startNodeId - 17));
-	      std::string::size_type xSpeedEnd = line.find_first_of (" ", endNodeId + 10);
-	      std::string::size_type ySpeedEnd = line.find_first_of (" ", xSpeedEnd + 1);
-	      double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
-	      double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
-	      double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
-	      NS_LOG_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
-	      Simulator::Schedule (Seconds (at), &StaticSpeedMobilityModel::SetSpeed, model,
-				   Vector (xSpeed, ySpeed, zSpeed));
-	    }
-	}
-      file.close();
-    }
-}
-
-void 
-Ns2MobilityFileTopology::Layout (void) const
-{
-  Layout (NodeList::Begin (), NodeList::End ());
-}
-
-} // namespace ns3
--- a/src/mobility/ns2-mobility-file-topology.h	Tue Feb 26 01:39:59 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,113 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-#ifndef NS2_MOBILITY_FILE_TOPOLOGY_H
-#define NS2_MOBILITY_FILE_TOPOLOGY_H
-
-#include <string>
-#include <stdint.h>
-#include "ns3/ptr.h"
-#include "ns3/object.h"
-#include "static-speed-mobility-model.h"
-
-namespace ns3 {
-
-/**
- * \brief a topology object which can read ns2's movement files
- *        generated by the CMU setdest tool.
- */
-class Ns2MobilityFileTopology
-{
-public:
-  /**
-   * \param filename filename of file which contains the
-   *        ns2 movement trace.
-   */
-  Ns2MobilityFileTopology (std::string filename);
-
-  /**
-   * Read the ns2 trace file and configure the movement
-   * patterns of all nodes contained in the global ns3::NodeList
-   * whose nodeId is matches the nodeId of the nodes in the trace
-   * file.
-   */
-  void Layout (void) const;
-
-  /**
-   * \param begin an iterator which points to the start of the input
-   *        object array.
-   * \param end an iterator which points to the end of the input
-   *        object array.
-   *
-   * Read the ns2 trace file and configure the movement
-   * patterns of all input objects. Each input object
-   * is identified by a unique node id which reflects
-   * the index of the object in the input array.
-   */
-  template <typename T>
-  void Layout (T begin, T end) const;
-private:
-  class ObjectStore
-  {
-  public:
-    virtual ~ObjectStore () {}
-    virtual Ptr<Object> Get (uint32_t i) const = 0;
-  };
-  void LayoutObjectStore (const ObjectStore &store) const;
-  Ptr<StaticSpeedMobilityModel> GetMobilityModel (std::string idString, const ObjectStore &store) const;
-  double ReadDouble (std::string valueString) const;
-  std::string m_filename;
-};
-
-} // namespace ns3
-
-namespace ns3 {
-
-template <typename T>
-void 
-Ns2MobilityFileTopology::Layout (T begin, T end) const
-{
-  class MyObjectStore : public ObjectStore
-  {
-  public:
-    MyObjectStore (T begin, T end)
-      : m_begin (begin),
-      m_end (end)
-	{}
-    virtual Ptr<Object> Get (uint32_t i) const {
-      T iterator = m_begin;
-      iterator += i;
-      if (iterator >= m_end)
-	{
-	  return 0;
-	}
-      return *iterator;
-    }
-  private:
-    T m_begin;
-    T m_end;
-  };
-  LayoutObjectStore (MyObjectStore (begin, end));
-}
-
-
-} // namespace ns3
-
-#endif /* NS2_MOBILITY_FILE_TOPOLOGY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/ns2-mobility-helper.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,163 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include <fstream>
+#include <sstream>
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/node-list.h"
+#include "ns3/node.h"
+#include "ns2-mobility-helper.h"
+#include "static-speed-mobility-model.h"
+#include "mobility-model-notifier.h"
+
+NS_LOG_COMPONENT_DEFINE ("Ns2MobilityHelper");
+
+namespace ns3 {
+
+
+Ns2MobilityHelper::Ns2MobilityHelper (std::string filename)
+  : m_filename (filename)
+{}
+
+void 
+Ns2MobilityHelper::EnableNotifier (void)
+{
+  m_notifierEnabled = true;
+}
+void 
+Ns2MobilityHelper::DisableNotifier (void)
+{
+  m_notifierEnabled = false;
+}
+
+
+
+Ptr<StaticSpeedMobilityModel>
+Ns2MobilityHelper::GetMobilityModel (std::string idString, const ObjectStore &store) const
+{
+  std::istringstream iss;
+  iss.str (idString);
+  uint32_t id;
+  iss >> id;
+  Ptr<Object> object = store.Get (id);
+  if (object == 0)
+    {
+      return 0;
+    }
+  Ptr<StaticSpeedMobilityModel> model = object->GetObject<StaticSpeedMobilityModel> ();
+  if (model == 0)
+    {
+      model = CreateObject<StaticSpeedMobilityModel> ();
+      object->AggregateObject (model);
+    }
+  Ptr<MobilityModelNotifier> notifier = object->GetObject<MobilityModelNotifier> ();
+  if (notifier == 0)
+    {
+      notifier = CreateObject<MobilityModelNotifier> ();
+      object->AggregateObject (notifier);
+    }
+  return model;
+}
+
+double
+Ns2MobilityHelper::ReadDouble (std::string valueString) const
+{
+  std::istringstream iss;
+  iss.str (valueString);
+  double value;
+  iss >> value;
+  return value;
+}
+
+void 
+Ns2MobilityHelper::LayoutObjectStore (const ObjectStore &store) const
+{
+  std::ifstream file (m_filename.c_str (), std::ios::in);
+  if (file.is_open())
+    {
+      while (!file.eof() )
+	{
+	  std::string line;
+	  getline (file, line);
+	  std::string::size_type startNodeId = line.find_first_of ("(");
+	  std::string::size_type endNodeId = line.find_first_of (")");
+	  if (startNodeId == std::string::npos ||
+	      endNodeId == std::string::npos)
+	    {
+	      continue;
+	    }
+	  Ptr<StaticSpeedMobilityModel> model = GetMobilityModel (line.substr (startNodeId + 1, 
+									       endNodeId - startNodeId), 
+								  store);
+	  if (model == 0)
+	    {
+	      continue;
+	    }
+	  if (startNodeId == 6)
+	    {
+	      double value = ReadDouble (line.substr (endNodeId + 9, std::string::npos));
+	      std::string coordinate = line.substr (endNodeId + 6, 1);
+              Vector position = model->GetPosition ();
+	      if (coordinate == "X")
+		{
+                  position.x = value;
+		  NS_LOG_DEBUG ("X=" << value);
+		}
+	      else if (coordinate == "Y")
+		{
+                  position.y = value;
+		  NS_LOG_DEBUG ("Y=" << value);
+		}
+	      else if (coordinate == "Z")
+		{
+                  position.z = value;
+		  NS_LOG_DEBUG ("Z=" << value);
+		}
+              else
+                {
+                  continue;
+                }
+              model->SetPosition (position);
+	    }
+	  else 
+	    {
+	      double at = ReadDouble (line.substr (8, startNodeId - 17));
+	      std::string::size_type xSpeedEnd = line.find_first_of (" ", endNodeId + 10);
+	      std::string::size_type ySpeedEnd = line.find_first_of (" ", xSpeedEnd + 1);
+	      double xSpeed = ReadDouble (line.substr (endNodeId + 10, xSpeedEnd - endNodeId - 10));
+	      double ySpeed = ReadDouble (line.substr (xSpeedEnd + 1, ySpeedEnd - xSpeedEnd - 1));
+	      double zSpeed = ReadDouble (line.substr (ySpeedEnd + 1, std::string::npos));
+	      NS_LOG_DEBUG ("at=" << at << "xSpeed=" << xSpeed << ", ySpeed=" << ySpeed << ", zSpeed=" << zSpeed);
+	      Simulator::Schedule (Seconds (at), &StaticSpeedMobilityModel::SetSpeed, model,
+				   Vector (xSpeed, ySpeed, zSpeed));
+	    }
+	}
+      file.close();
+    }
+}
+
+void 
+Ns2MobilityHelper::Layout (void) const
+{
+  Layout (NodeList::Begin (), NodeList::End ());
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/ns2-mobility-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,117 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef NS2_MOBILITY_FILE_TOPOLOGY_H
+#define NS2_MOBILITY_FILE_TOPOLOGY_H
+
+#include <string>
+#include <stdint.h>
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+#include "static-speed-mobility-model.h"
+
+namespace ns3 {
+
+/**
+ * \brief a topology object which can read ns2's movement files
+ *        generated by the CMU setdest tool.
+ */
+class Ns2MobilityHelper
+{
+public:
+  /**
+   * \param filename filename of file which contains the
+   *        ns2 movement trace.
+   */
+  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
+   * whose nodeId is matches the nodeId of the nodes in the trace
+   * file.
+   */
+  void Layout (void) const;
+
+  /**
+   * \param begin an iterator which points to the start of the input
+   *        object array.
+   * \param end an iterator which points to the end of the input
+   *        object array.
+   *
+   * Read the ns2 trace file and configure the movement
+   * patterns of all input objects. Each input object
+   * is identified by a unique node id which reflects
+   * the index of the object in the input array.
+   */
+  template <typename T>
+  void Layout (T begin, T end) const;
+private:
+  class ObjectStore
+  {
+  public:
+    virtual ~ObjectStore () {}
+    virtual Ptr<Object> Get (uint32_t i) const = 0;
+  };
+  void LayoutObjectStore (const ObjectStore &store) const;
+  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
+
+namespace ns3 {
+
+template <typename T>
+void 
+Ns2MobilityHelper::Layout (T begin, T end) const
+{
+  class MyObjectStore : public ObjectStore
+  {
+  public:
+    MyObjectStore (T begin, T end)
+      : m_begin (begin),
+      m_end (end)
+	{}
+    virtual Ptr<Object> Get (uint32_t i) const {
+      T iterator = m_begin;
+      iterator += i;
+      if (iterator >= m_end)
+	{
+	  return 0;
+	}
+      return *iterator;
+    }
+  private:
+    T m_begin;
+    T m_end;
+  };
+  LayoutObjectStore (MyObjectStore (begin, end));
+}
+
+
+} // namespace ns3
+
+#endif /* NS2_MOBILITY_FILE_TOPOLOGY_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/position-allocator.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,190 @@
+/* -*-  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 "position-allocator.h"
+#include "ns3/random-variable.h"
+#include "ns3/double.h"
+#include "ns3/integer.h"
+#include "ns3/enum.h"
+#include "ns3/log.h"
+#include <cmath>
+
+NS_LOG_COMPONENT_DEFINE ("PositionAllocator");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (PositionAllocator);
+
+TypeId 
+PositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("PositionAllocator")
+    .SetParent<Object> ();
+  return tid;
+}
+
+PositionAllocator::PositionAllocator ()
+{
+}
+
+PositionAllocator::~PositionAllocator ()
+{}
+
+TypeId 
+GridPositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("GridPositionAllocator")
+    .SetParent<PositionAllocator> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<GridPositionAllocator> ()
+    .AddAttribute ("GridWidth", "The number of objects layed out on a line.",
+                   Integer (10),
+                   MakeIntegerAccessor (&GridPositionAllocator::m_n),
+                   MakeIntegerChecker<uint32_t> ())
+    .AddAttribute ("MinX", "The x coordinate where the grid starts.",
+                   Double (1.0),
+                   MakeDoubleAccessor (&GridPositionAllocator::m_xMin),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MinY", "The y coordinate where the grid starts.",
+                   Double (0.0),
+                   MakeDoubleAccessor (&GridPositionAllocator::m_yMin),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("DeltaX", "The x space between objects.",
+                   Double (1.0),
+                   MakeDoubleAccessor (&GridPositionAllocator::m_deltaX),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("DeltaY", "The y space between objects.",
+                   Double (1.0),
+                   MakeDoubleAccessor (&GridPositionAllocator::m_deltaY),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("LayoutType", "The type of layout.",
+                   Enum (ROW_FIRST),
+                   MakeEnumAccessor (&GridPositionAllocator::m_layoutType),
+                   MakeEnumChecker (ROW_FIRST, "RowFirst",
+                                    COLUMN_FIRST, "ColumnFirst"))
+    ;
+  return tid;
+}
+GridPositionAllocator::GridPositionAllocator ()
+  : m_current (0)
+{}
+
+Vector 
+GridPositionAllocator::GetNext (void) const
+{
+  double x = 0.0, y = 0.0;
+  switch (m_layoutType) {
+  case ROW_FIRST:
+    x = m_xMin + m_deltaX * (m_current % m_n);
+    y = m_yMin + m_deltaY * (m_current / m_n);
+    break;
+  case COLUMN_FIRST:
+    x = m_xMin + m_deltaX * (m_current / m_n);
+    y = m_yMin + m_deltaY * (m_current % m_n);
+    break;
+  }
+  m_current++;
+  return Vector (x, y, 0.0);
+}
+
+
+NS_OBJECT_ENSURE_REGISTERED (RandomRectanglePositionAllocator);
+
+TypeId
+RandomRectanglePositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("RandomRectanglePositionAllocator")
+    .SetParent<PositionAllocator> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<RandomRectanglePositionAllocator> ()
+    .AddAttribute ("X",
+                   "A random variable which represents the x coordinate of a position in a random rectangle.",
+                   UniformVariable (0.0, 1.0),
+                   MakeRandomVariableAccessor (&RandomRectanglePositionAllocator::m_x),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("Y",
+                   "A random variable which represents the y coordinate of a position in a random rectangle.",
+                   UniformVariable (0.0, 1.0),
+                   MakeRandomVariableAccessor (&RandomRectanglePositionAllocator::m_y),
+                   MakeRandomVariableChecker ());
+  return tid;
+}
+
+RandomRectanglePositionAllocator::RandomRectanglePositionAllocator ()
+{}
+RandomRectanglePositionAllocator::~RandomRectanglePositionAllocator ()
+{}
+Vector
+RandomRectanglePositionAllocator::GetNext (void) const
+{
+  double x = m_x.GetValue ();
+  double y = m_y.GetValue ();
+  return Vector (x, y, 0.0);
+}
+
+NS_OBJECT_ENSURE_REGISTERED (RandomDiscPositionAllocator);
+
+TypeId
+RandomDiscPositionAllocator::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("RandomDiscPositionAllocator")
+    .SetParent<PositionAllocator> ()
+    .SetGroupName ("Mobility")
+    .AddConstructor<RandomDiscPositionAllocator> ()
+    .AddAttribute ("Theta",
+                   "A random variable which represents the angle (gradients) of a position in a random disc.",
+                   UniformVariable (0.0, 6.2830),
+                   MakeRandomVariableAccessor (&RandomDiscPositionAllocator::m_theta),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("Rho",
+                   "A random variable which represents the radius of a position in a random disc.",
+                   UniformVariable (0.0, 200.0),
+                   MakeRandomVariableAccessor (&RandomDiscPositionAllocator::m_rho),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("X",
+                   "The x coordinate of the center of the random position disc.",
+                   Double (0.0),
+                   MakeDoubleAccessor (&RandomDiscPositionAllocator::m_x),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("Y",
+                   "The y coordinate of the center of the random position disc.",
+                   Double (0.0),
+                   MakeDoubleAccessor (&RandomDiscPositionAllocator::m_y),
+                   MakeDoubleChecker<double> ())
+    ;
+  return tid;
+}   
+
+RandomDiscPositionAllocator::RandomDiscPositionAllocator ()
+{}
+RandomDiscPositionAllocator::~RandomDiscPositionAllocator ()
+{}
+Vector
+RandomDiscPositionAllocator::GetNext (void) const
+{
+  double theta = m_theta.GetValue ();
+  double rho = m_rho.GetValue ();
+  double x = m_x + std::cos (theta) * rho;
+  double y = m_y + std::sin (theta) * rho;
+  NS_LOG_DEBUG ("Disc position x=" << x << ", y=" << y);
+  return Vector (x, y, 0.0);
+}
+
+
+} // namespace ns3 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/mobility/position-allocator.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,105 @@
+/* -*-  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 POSITION_ALLOCATOR_H
+#define POSITION_ALLOCATOR_H
+
+#include "ns3/object.h"
+#include "ns3/random-variable.h"
+#include "vector.h"
+
+namespace ns3 {
+
+/**
+ * \brief choose a position at random.
+ *
+ * This is a pure abstract base class.
+ */
+class PositionAllocator : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  PositionAllocator ();
+  virtual ~PositionAllocator ();
+  /**
+   * \returns the next randomly-choosen position.
+   */
+  virtual Vector GetNext (void) const = 0;
+};
+
+class GridPositionAllocator : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  enum LayoutType {
+    ROW_FIRST,
+    COLUMN_FIRST
+  };
+
+  GridPositionAllocator ();
+
+  virtual Vector GetNext (void) const;
+private:
+  mutable uint32_t m_current;
+  enum LayoutType m_layoutType;
+  double m_xMin;
+  double m_yMin;
+  uint32_t m_n;
+  double m_deltaX;
+  double m_deltaY;
+};
+
+/**
+ * \brief allocate random positions within a rectangle
+ * according to a pair of random variables.
+ */
+class RandomRectanglePositionAllocator : public PositionAllocator
+{
+public:
+  static TypeId GetTypeId (void);
+  RandomRectanglePositionAllocator ();
+  virtual ~RandomRectanglePositionAllocator ();
+  virtual Vector GetNext (void) const;
+private:
+  RandomVariable m_x;
+  RandomVariable m_y;
+};
+
+/**
+ * \brief allocate random positions within a disc
+ * according to a pair of random variables.
+ */
+class RandomDiscPositionAllocator : public PositionAllocator
+{
+public:
+  static TypeId GetTypeId (void);
+  RandomDiscPositionAllocator ();
+  virtual ~RandomDiscPositionAllocator ();
+  virtual Vector GetNext (void) const;
+private:
+  RandomVariable m_theta;
+  RandomVariable m_rho;
+  double m_x;
+  double m_y;
+};
+
+} // namespace ns3
+
+#endif /* RANDOM_POSITION_H */
--- a/src/mobility/random-direction-2d-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-direction-2d-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -19,7 +19,6 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "ns3/random-variable-default-value.h"
-#include "ns3/rectangle-default-value.h"
 #include "ns3/simulator.h"
 #include <algorithm>
 #include <cmath>
@@ -35,100 +34,37 @@
 NS_OBJECT_ENSURE_REGISTERED (RandomDirection2dMobilityModel);
 
 
-static RandomVariableDefaultValue 
-  g_speedVariable ("RandomDirection2dSpeed",
-		   "A random variable to control the speed of a RandomDirection2d mobility model.",
-		   "Uniform:1:2");
-
-static RandomVariableDefaultValue
-  g_pauseVariable ("RandomDirection2dPause",
-		   "A random variable to control the duration "
-                   "of the pause of a RandomDiretion mobility model.",
-		   "Constant:2");
-
-static RectangleDefaultValue
-  g_bounds ("RandomDirection2dArea",
-	       "The bounding area for the RandomDirection2d model.",
-	       -100, 100, -100, 100);
-
-
-RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters ()
-  : m_bounds (g_bounds.GetValue ()),
-    m_speedVariable (g_speedVariable.Get ()),
-    m_pauseVariable (g_pauseVariable.Get ())
-    
-{}
-RandomDirection2dMobilityModelParameters::RandomDirection2dMobilityModelParameters 
-(const Rectangle &bounds,
- const RandomVariable &speedVariable,
- const RandomVariable &pauseVariable)
-  : m_bounds (bounds),
-    m_speedVariable (speedVariable),
-    m_pauseVariable (pauseVariable)
-{}
-
-RandomDirection2dMobilityModelParameters::~RandomDirection2dMobilityModelParameters ()
-{}
-
-void 
-RandomDirection2dMobilityModelParameters::SetSpeed (const RandomVariable &speedVariable)
-{
-  m_speedVariable = speedVariable;
-}
-void 
-RandomDirection2dMobilityModelParameters::SetPause (const RandomVariable &pauseVariable)
-{
-  m_pauseVariable = pauseVariable;
-}
-void 
-RandomDirection2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
-{
-  m_bounds = bounds;
-}
-
-Ptr<RandomDirection2dMobilityModelParameters> 
-RandomDirection2dMobilityModelParameters::GetCurrent (void)
-{
-  static Ptr<RandomDirection2dMobilityModelParameters> parameters = 0;
-  if (parameters == 0 ||
-      g_bounds.IsDirty () ||
-      g_speedVariable.IsDirty () ||
-      g_pauseVariable.IsDirty ())
-    {
-      parameters = CreateObject<RandomDirection2dMobilityModelParameters> ();
-      g_bounds.ClearDirtyFlag ();
-      g_speedVariable.ClearDirtyFlag ();
-      g_pauseVariable.ClearDirtyFlag ();
-    }
-  return parameters;
-}
-
 TypeId
 RandomDirection2dMobilityModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("RandomDirection2dMobilityModel")
     .SetParent<MobilityModel> ()
+    .SetGroupName ("Mobility")
     .AddConstructor<RandomDirection2dMobilityModel> ()
-    .AddConstructor<RandomDirection2dMobilityModel,Ptr<RandomDirection2dMobilityModelParameters> > ();
+    .AddAttribute ("bounds", "The 2d bounding area",
+                   Rectangle (-100, 100, -100, 100),
+                   MakeRectangleAccessor (&RandomDirection2dMobilityModel::m_bounds),
+                   MakeRectangleChecker ())
+    .AddAttribute ("speed", "A random variable to control the speed (m/s).",
+                   UniformVariable (1.0, 2.0),
+                   MakeRandomVariableAccessor (&RandomDirection2dMobilityModel::m_speed),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("pause", "A random variable to control the pause (s).",
+                   ConstantVariable (2.0),
+                   MakeRandomVariableAccessor (&RandomDirection2dMobilityModel::m_pause),
+                   MakeRandomVariableChecker ())
+    ;
   return tid;
 }
 
 
 RandomDirection2dMobilityModel::RandomDirection2dMobilityModel ()
-  : m_parameters (RandomDirection2dMobilityModelParameters::GetCurrent ())
-{
-  m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
-}
-RandomDirection2dMobilityModel::RandomDirection2dMobilityModel 
-(Ptr<RandomDirection2dMobilityModelParameters> parameters)
-  : m_parameters (parameters)
 {
   m_event = Simulator::ScheduleNow (&RandomDirection2dMobilityModel::Start, this);
 }
 void 
 RandomDirection2dMobilityModel::DoDispose (void)
 {
-  m_parameters = 0;
   // chain up.
   MobilityModel::DoDispose ();
 }
@@ -142,7 +78,7 @@
 void
 RandomDirection2dMobilityModel::BeginPause (void)
 {
-  Time pause = Seconds (m_parameters->m_pauseVariable.GetValue ());
+  Time pause = Seconds (m_pause.GetValue ());
   m_helper.Pause ();
   m_event = Simulator::Schedule (pause, &RandomDirection2dMobilityModel::ResetDirectionAndSpeed, this);
   NotifyCourseChange ();
@@ -152,13 +88,13 @@
 RandomDirection2dMobilityModel::SetDirectionAndSpeed (double direction)
 {
   NS_LOG_FUNCTION;
-  double speed = m_parameters->m_speedVariable.GetValue ();
+  double speed = m_speed.GetValue ();
   const Vector vector (std::cos (direction) * speed,
                        std::sin (direction) * speed,
                        0.0);
-  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  Vector position = m_helper.GetCurrentPosition (m_bounds);
   m_helper.Reset (vector);
-  Vector next = m_parameters->m_bounds.CalculateIntersection (position, vector);
+  Vector next = m_bounds.CalculateIntersection (position, vector);
   Time delay = Seconds (CalculateDistance (position, next) / speed);
   m_event = Simulator::Schedule (delay,
 				 &RandomDirection2dMobilityModel::BeginPause, this);
@@ -169,8 +105,8 @@
 {
   double direction = UniformVariable::GetSingleValue (0, PI);
   
-  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
-  switch (m_parameters->m_bounds.GetClosestSide (position))
+  Vector position = m_helper.GetCurrentPosition (m_bounds);
+  switch (m_bounds.GetClosestSide (position))
     {
     case Rectangle::RIGHT:
       direction += PI / 2;
@@ -190,7 +126,7 @@
 Vector
 RandomDirection2dMobilityModel::DoGetPosition (void) const
 {
-  return m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  return m_helper.GetCurrentPosition (m_bounds);
 }
 void
 RandomDirection2dMobilityModel::DoSetPosition (const Vector &position)
--- a/src/mobility/random-direction-2d-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-direction-2d-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -33,50 +33,6 @@
 namespace ns3 {
 
 /**
- * \brief the parameters to control a RandomDirection mobility model.
- */
-class RandomDirection2dMobilityModelParameters : public Object
-{
- public:
-  /**
-   * Create from \valueref{RandomDirection2dSpeed},
-   * \valueref{RandomDirection2dPause}, and,
-   * \valueref{RandomDirection2dArea}.
-   */
-  RandomDirection2dMobilityModelParameters ();
-  /**
-   * \param bounds the 2d bounds of the mobility model
-   * \param speedVariable the random variable used to pick a random speed
-   * \param pauseVariable the random variable used to pick a random pause delay
-   */
-  RandomDirection2dMobilityModelParameters (const Rectangle &bounds,
-                               const RandomVariable &speedVariable,
-                               const RandomVariable &pauseVariable);
-  virtual ~RandomDirection2dMobilityModelParameters ();
-
-  /**
-   * \param speedVariable the random variable used to pick a random speed.
-   */
-  void SetSpeed (const RandomVariable &speedVariable);
-  /**
-   * \param pauseVariable the random variable used to pick a random pause delay.
-   */
-  void SetPause (const RandomVariable &pauseVariable);
-  /**
-   * \param bounds the 2d bounds of the mobility model.
-   */
-  void SetBounds (const Rectangle &bounds);
- private:
-  friend class RandomDirection2dMobilityModel;
-
-  static Ptr<RandomDirection2dMobilityModelParameters> GetCurrent (void);
-
-  Rectangle m_bounds;
-  RandomVariable m_speedVariable;
-  RandomVariable m_pauseVariable;
-};
-
-/**
  * \brief a RandomDirection mobility model
  *
  * The movement of objects is based on random directions: each object
@@ -96,11 +52,6 @@
    * \valueref{RandomDirection2dArea}.
    */
   RandomDirection2dMobilityModel ();
-  /**
-   * \param parameters the parameters which control the behavior of the model.
-   * Create a RandomDirection model using the parameters specified.
-   */
-  RandomDirection2dMobilityModel (Ptr<RandomDirection2dMobilityModelParameters> parameters);
  private:
   void Start (void);
   void ResetDirectionAndSpeed (void);
@@ -113,7 +64,9 @@
   virtual Vector DoGetVelocity (void) const;
 
   static const double PI;
-  Ptr<RandomDirection2dMobilityModelParameters> m_parameters;
+  Rectangle m_bounds;
+  RandomVariable m_speed;
+  RandomVariable m_pause;
   EventId m_event;
   StaticSpeedHelper m_helper;
 };
--- a/src/mobility/random-position.cc	Tue Feb 26 01:39:59 2008 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +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 "random-position.h"
-#include "ns3/random-variable.h"
-#include "ns3/default-value.h"
-#include "ns3/random-variable-default-value.h"
-#include "ns3/log.h"
-#include <cmath>
-
-NS_LOG_COMPONENT_DEFINE ("RandomPosition");
-
-namespace ns3 {
-
-static RandomVariableDefaultValue
-g_rectangleX ("RandomRectanglePositionX",
-	      "A random variable which represents the x position of a position in a random rectangle.",
-	      "Uniform:0:200");
-
-static RandomVariableDefaultValue
-g_rectangleY ("RandomRectanglePositionY",
-	      "A random variable which represents the y position of a position in a random rectangle.",
-	      "Uniform:0:200");
-
-static RandomVariableDefaultValue
-g_discTheta ("RandomDiscPositionTheta",
-	     "A random variable which represents the angle (gradients) of a position in a random disc.",
-	     "Uniform:0:6.2830");
-
-static RandomVariableDefaultValue
-g_discRho ("RandomDiscPositionRho",
-	   "A random variable which represents the radius of a position in a random disc.",
-	   "Uniform:0:200");
-
-static NumericDefaultValue<double>
-g_discX ("RandomDiscPositionX",
-	 "The x coordinate of the center of the random position disc.",
-	 0.0);
-
-static NumericDefaultValue<double>
-g_discY ("RandomDiscPositionY",
-	 "The y coordinate of the center of the random position disc.",
-	 0.0);
-
-NS_OBJECT_ENSURE_REGISTERED (RandomPosition);
-
-TypeId 
-RandomPosition::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("RandomPosition")
-    .SetParent<Object> ();
-  return tid;
-}
-
-RandomPosition::RandomPosition ()
-{
-}
-
-RandomPosition::~RandomPosition ()
-{}
-
-NS_OBJECT_ENSURE_REGISTERED (RandomRectanglePosition);
-
-TypeId
-RandomRectanglePosition::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("RandomRectanglePosition")
-    .SetParent<RandomPosition> ()
-    .AddConstructor<RandomRectanglePosition> ()
-    .AddConstructor<RandomRectanglePosition, const RandomVariable &, const RandomVariable &> ();
-  return tid;
-}
-
-RandomRectanglePosition::RandomRectanglePosition ()
-  : m_x (g_rectangleX.Get ()),
-    m_y (g_rectangleY.Get ())
-{}
-RandomRectanglePosition::RandomRectanglePosition (const RandomVariable &x,
-						  const RandomVariable &y)
-  : m_x (x),
-    m_y (y)
-{}
-RandomRectanglePosition::~RandomRectanglePosition ()
-{}
-Vector
-RandomRectanglePosition::Get (void) const
-{
-  double x = m_x.GetValue ();
-  double y = m_y.GetValue ();
-  return Vector (x, y, 0.0);
-}
-
-NS_OBJECT_ENSURE_REGISTERED (RandomDiscPosition);
-
-TypeId
-RandomDiscPosition::GetTypeId (void)
-{
-  static TypeId tid = TypeId ("RandomDiscPosition")
-    .SetParent<RandomPosition> ()
-    .AddConstructor<RandomDiscPosition> ()
-    .AddConstructor<RandomDiscPosition, const RandomVariable &, const RandomVariable &, double, double> ();
-  return tid;
-}   
-
-RandomDiscPosition::RandomDiscPosition ()
-  : m_theta (g_discTheta.Get ()),
-    m_rho (g_discRho.Get ()),
-    m_x (g_discX.GetValue ()),
-    m_y (g_discY.GetValue ())
-{}
-RandomDiscPosition::RandomDiscPosition (const RandomVariable &theta,
-					const RandomVariable &rho,
-					double x, double y)
-  : m_theta (theta),
-    m_rho (rho),
-    m_x (0.0),
-    m_y (0.0)
-{}
-RandomDiscPosition::~RandomDiscPosition ()
-{}
-Vector
-RandomDiscPosition::Get (void) const
-{
-  double theta = m_theta.GetValue ();
-  double rho = m_rho.GetValue ();
-  double x = m_x + std::cos (theta) * rho;
-  double y = m_y + std::sin (theta) * rho;
-  NS_LOG_DEBUG ("Disc position x=" << x << ", y=" << y);
-  return Vector (x, y, 0.0);
-}
-
-
-} // namespace ns3 
--- a/src/mobility/random-position.h	Tue Feb 26 01:39:59 2008 +0100
+++ /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>
- */
-#ifndef RANDOM_POSITION_H
-#define RANDOM_POSITION_H
-
-#include "ns3/object.h"
-#include "ns3/random-variable.h"
-#include "vector.h"
-
-namespace ns3 {
-
-/**
- * \brief choose a position at random.
- *
- * This is a pure abstract base class.
- */
-class RandomPosition : public Object
-{
-public:
-  static TypeId GetTypeId (void);
-  RandomPosition ();
-  virtual ~RandomPosition ();
-  /**
-   * \returns the next randomly-choosen position.
-   */
-  virtual Vector Get (void) const = 0;
-};
-
-/**
- * \brief allocate random positions within a rectangle
- * according to a pair of random variables.
- */
-class RandomRectanglePosition : public RandomPosition
-{
-public:
-  static TypeId GetTypeId (void);
-  /**
-   * Create a random position model with construction
-   * values from \valueref{RandomRectanglePositionX}, and
-   * \valueref{RandomRectanglePositionY}
-   */
-  RandomRectanglePosition ();
-  /**
-   * \param x the random variable which is used to choose
-   *        the x coordinates.
-   * \param y the random variable which is used to choose
-   *        the y coordinates.
-   */
-  RandomRectanglePosition (const RandomVariable &x,
-			   const RandomVariable &y);
-  virtual ~RandomRectanglePosition ();
-  virtual Vector Get (void) const;
-private:
-  RandomVariable m_x;
-  RandomVariable m_y;
-};
-
-/**
- * \brief allocate random positions within a disc
- * according to a pair of random variables.
- */
-class RandomDiscPosition : public RandomPosition
-{
-public:
-  static TypeId GetTypeId (void);
-  /**
-   * Create a random position model with construction
-   * values from \valueref{RandomDiscPositionTheta},
-   * \valueref{RandomDiscPositionRho}, 
-   * \valueref{RandomDiscPositionX}, and,
-   * \valueref{RandomDiscPositionY}.
-   */
-  RandomDiscPosition ();
-  /**
-   * \param theta the random variable used to pick
-   *        the angle of the random position in polar
-   *        coordinates.
-   * \param rho the random variable used to pick the
-   *        radius of the random position in polar
-   *        coordinates.
-   * \param x the x coordinate of the center of the
-   *        polar coodinate system.
-   * \param y the y coordinate of the center of the
-   *        polar coodinate system.
-   */
-  RandomDiscPosition (const RandomVariable &theta,
-		      const RandomVariable &rho,
-		      double x, double y);
-  virtual ~RandomDiscPosition ();
-  virtual Vector Get (void) const;
-private:
-  RandomVariable m_theta;
-  RandomVariable m_rho;
-  double m_x;
-  double m_y;
-};
-
-} // namespace ns3
-
-#endif /* RANDOM_POSITION_H */
--- a/src/mobility/random-walk-2d-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-walk-2d-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -19,10 +19,7 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "random-walk-2d-mobility-model.h"
-#include "ns3/default-value.h"
-#include "ns3/time-default-value.h"
-#include "ns3/rectangle-default-value.h"
-#include "ns3/random-variable-default-value.h"
+#include "ns3/enum.h"
 #include "ns3/simulator.h"
 #include "ns3/log.h"
 #include <cmath>
@@ -33,113 +30,49 @@
 
 NS_OBJECT_ENSURE_REGISTERED (RandomWalk2dMobilityModel);
 
-static EnumDefaultValue<RandomWalk2dMobilityModelParameters::Mode> 
-g_mode ("RandomWalk2dMode",
-        "The mode indicates the condition used to "
-        "change the current speed and direction",
-        RandomWalk2dMobilityModelParameters::MODE_DISTANCE, "Distance",
-        RandomWalk2dMobilityModelParameters::MODE_TIME, "Time",
-        0, (void*)0);
-
-static NumericDefaultValue<double>
-g_modeDistance ("RandomWalk2dDistance",
-                "Change current direction and speed after moving this distance.",
-                2.0);
-
-static TimeDefaultValue
-g_modeTime ("RandomWalk2dTime",
-             "Change current direction and speed after moving for this delay.",
-             Seconds (1.0));
-
-static RandomVariableDefaultValue
-g_speed ("RandomWalk2dSpeed",
-         "A random variable used to pick the speed.",
-         "Uniform:2:4");
-static RandomVariableDefaultValue
-g_direction ("RandomWalk2dDirection",
-             "A random variable used to pick the direction (gradients).",
-             "Uniform:0.0:6.283184");
-
-static RectangleDefaultValue
-g_rectangle ("RandomWalk2dBounds",
-             "Bounds of the area to cruise.",
-             0.0, 0.0, 100.0, 100.0);
-
-RandomWalk2dMobilityModelParameters::RandomWalk2dMobilityModelParameters ()
-  : m_mode (g_mode.GetValue ()),
-    m_modeDistance (g_modeDistance.GetValue ()),
-    m_modeTime (g_modeTime.GetValue ()),
-    m_speed (g_speed.Get ()),
-    m_direction (g_direction.Get ()),
-    m_bounds (g_rectangle.GetValue ())
-{}
-
-RandomWalk2dMobilityModelParameters::~RandomWalk2dMobilityModelParameters ()
-{}
-
-void 
-RandomWalk2dMobilityModelParameters::SetSpeed (const RandomVariable &speed)
-{
-  m_speed = speed;
-}
-void 
-RandomWalk2dMobilityModelParameters::SetDirection (const RandomVariable &direction)
-{
-  m_direction = direction;
-}
-void 
-RandomWalk2dMobilityModelParameters::SetModeDistance (double distance)
-{
-  m_mode = RandomWalk2dMobilityModelParameters::MODE_DISTANCE;
-  m_modeDistance = distance;
-}
-void 
-RandomWalk2dMobilityModelParameters::SetModeTime (Time time)
-{
-  m_mode = RandomWalk2dMobilityModelParameters::MODE_TIME;
-  m_modeTime = time;
-}
-void 
-RandomWalk2dMobilityModelParameters::SetBounds (const Rectangle &bounds)
-{
-  m_bounds = bounds;
-}
-
-Ptr<RandomWalk2dMobilityModelParameters> 
-RandomWalk2dMobilityModelParameters::GetCurrent (void)
-{
-  static Ptr<RandomWalk2dMobilityModelParameters> parameters = 0;
-  if (parameters == 0 ||
-      g_speed.IsDirty () ||
-      g_direction.IsDirty () ||
-      g_mode.IsDirty () ||
-      g_modeDistance.IsDirty () ||
-      g_modeTime.IsDirty () ||
-      g_rectangle.IsDirty ())
-    {
-      parameters = CreateObject<RandomWalk2dMobilityModelParameters> ();
-    }
-  return parameters;
-}
-
 TypeId
 RandomWalk2dMobilityModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("RandomWalkMobilityModel")
     .SetParent<MobilityModel> ()
+    .SetGroupName ("Mobility")
     .AddConstructor<RandomWalk2dMobilityModel> ()
-    .AddConstructor<RandomWalk2dMobilityModel,Ptr<RandomWalk2dMobilityModelParameters> > ();
+    .AddAttribute ("bounds",
+                   "Bounds of the area to cruise.",
+                   Rectangle (0.0, 0.0, 100.0, 100.0),
+                   MakeRectangleAccessor (&RandomWalk2dMobilityModel::m_bounds),
+                   MakeRectangleChecker ())
+    .AddAttribute ("time",
+                   "Change current direction and speed after moving for this delay.",
+                   Seconds (1.0),
+                   MakeTimeAccessor (&RandomWalk2dMobilityModel::m_modeTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("distance",
+                   "Change current direction and speed after moving for this distance.",
+                   Seconds (1.0),
+                   MakeTimeAccessor (&RandomWalk2dMobilityModel::m_modeTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("mode",
+                   "The mode indicates the condition used to "
+                   "change the current speed and direction",
+                   Enum (RandomWalk2dMobilityModel::MODE_DISTANCE),
+                   MakeEnumAccessor (&RandomWalk2dMobilityModel::m_mode),
+                   MakeEnumChecker (RandomWalk2dMobilityModel::MODE_DISTANCE, "Distance",
+                                    RandomWalk2dMobilityModel::MODE_TIME, "Time"))
+    .AddAttribute ("direction",
+                   "A random variable used to pick the direction (gradients).",
+                   UniformVariable (0.0, 6.283184),
+                   MakeRandomVariableAccessor (&RandomWalk2dMobilityModel::m_direction),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("speed",
+                   "A random variable used to pick the speed (m/s).",
+                   UniformVariable (2.0, 4.0),
+                   MakeRandomVariableAccessor (&RandomWalk2dMobilityModel::m_speed),
+                   MakeRandomVariableChecker ());
   return tid;
 }
 
 RandomWalk2dMobilityModel::RandomWalk2dMobilityModel ()
-  : m_parameters (RandomWalk2dMobilityModelParameters::GetCurrent ())
-{
-  m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
-}
-
-RandomWalk2dMobilityModel::RandomWalk2dMobilityModel (Ptr<RandomWalk2dMobilityModelParameters> parameters)
-  : m_parameters (parameters)
 {
   m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
 }
@@ -147,21 +80,21 @@
 void
 RandomWalk2dMobilityModel::Start (void)
 {
-  double speed = m_parameters->m_speed.GetValue ();
-  double direction = m_parameters->m_direction.GetValue ();
+  double speed = m_speed.GetValue ();
+  double direction = m_direction.GetValue ();
   Vector vector (std::cos (direction) * speed,
                  std::sin (direction) * speed,
                  0.0);
   m_helper.Reset (vector);
 
   Time delayLeft;
-  if (m_parameters->m_mode == RandomWalk2dMobilityModelParameters::MODE_TIME)
+  if (m_mode == RandomWalk2dMobilityModel::MODE_TIME)
     {
-      delayLeft = m_parameters->m_modeTime;
+      delayLeft = m_modeTime;
     }
   else
     {
-      delayLeft = Seconds (m_parameters->m_modeDistance / speed); 
+      delayLeft = Seconds (m_modeDistance / speed); 
     }
   DoWalk (delayLeft);
 }
@@ -174,13 +107,13 @@
   Vector nextPosition = position;
   nextPosition.x += speed.x * delayLeft.GetSeconds ();
   nextPosition.y += speed.y * delayLeft.GetSeconds ();
-  if (m_parameters->m_bounds.IsInside (nextPosition))
+  if (m_bounds.IsInside (nextPosition))
     {
       m_event = Simulator::Schedule (delayLeft, &RandomWalk2dMobilityModel::Start, this);
     }
   else
     {
-      nextPosition = m_parameters->m_bounds.CalculateIntersection (position, speed);
+      nextPosition = m_bounds.CalculateIntersection (position, speed);
       Time delay = Seconds ((nextPosition.x - position.x) / speed.x);
       m_event = Simulator::Schedule (delay, &RandomWalk2dMobilityModel::Rebound, this,
                                      delayLeft - delay);      
@@ -191,9 +124,9 @@
 void
 RandomWalk2dMobilityModel::Rebound (Time delayLeft)
 {
-  Vector position = m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  Vector position = m_helper.GetCurrentPosition (m_bounds);
   Vector speed = m_helper.GetVelocity ();
-  switch (m_parameters->m_bounds.GetClosestSide (position))
+  switch (m_bounds.GetClosestSide (position))
     {
     case Rectangle::RIGHT:
     case Rectangle::LEFT:
@@ -211,19 +144,18 @@
 void
 RandomWalk2dMobilityModel::DoDispose (void)
 {
-  m_parameters = 0;
   // chain up
   MobilityModel::DoDispose ();
 }
 Vector
 RandomWalk2dMobilityModel::DoGetPosition (void) const
 {
-  return m_helper.GetCurrentPosition (m_parameters->m_bounds);
+  return m_helper.GetCurrentPosition (m_bounds);
 }
 void
 RandomWalk2dMobilityModel::DoSetPosition (const Vector &position)
 {
-  NS_ASSERT (m_parameters->m_bounds.IsInside (position));
+  NS_ASSERT (m_bounds.IsInside (position));
   m_helper.InitializePosition (position);
   Simulator::Remove (m_event);
   m_event = Simulator::ScheduleNow (&RandomWalk2dMobilityModel::Start, this);
--- a/src/mobility/random-walk-2d-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-walk-2d-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -33,72 +33,6 @@
 
 
 /**
- * \brief parameters to control a random walk 2d model
- *
- * A single parameter object can be shared by multiple random
- * walk models.
- */
-class RandomWalk2dMobilityModelParameters : public Object
-{
- public:
-  /**
-   * Instantiate a set of RandomWalk parameters initialized
-   * with construction values from \valueref{RandomWalk2dMode},
-   * \valueref{RandomWalk2dDistance}, \valueref{RandomWalk2dTime},
-   * \valueref{RandomWalk2dSpeed}, \valueref{RandomWalk2dDirection},
-   * and, \valueref{RandomWalk2dBounds}.
-   */
-  RandomWalk2dMobilityModelParameters ();
-  virtual ~RandomWalk2dMobilityModelParameters ();
-  /**
-   * \param speed the random variable used to pick a new
-   *        speed when the direction is changed.
-   *
-   */
-  void SetSpeed (const RandomVariable &speed);
-  /**
-   * \param direction the random variable used to pick a new
-   *        direction.
-   */
-  void SetDirection (const RandomVariable &direction);
-  /**
-   * \param distance the distance before a direction change
-   *
-   * Unit is meters.
-   * "time" mode is incompatible with "distance" mode.
-   */
-  void SetModeDistance (double distance);
-  /**
-   * \param time the delay before a direction change.
-   *
-   * "time" mode is incompatible with "distance" mode.
-   */
-  void SetModeTime (Time time);
-
-  /**
-   * \param bounds the bounds of the random walk
-   */
-  void SetBounds (const Rectangle &bounds);
-
-
-  // needed public for internal default value code.
-  enum Mode  {
-    MODE_DISTANCE,
-    MODE_TIME
-  };
- private:
-  friend class RandomWalk2dMobilityModel;
-  static Ptr<RandomWalk2dMobilityModelParameters> GetCurrent (void);
-
-  enum Mode m_mode;
-  double m_modeDistance;
-  Time m_modeTime;
-  RandomVariable m_speed;
-  RandomVariable m_direction;
-  Rectangle m_bounds;
-};
-
-/**
  * \brief a 2D random walk position model
  *
  * Each instance moves with a speed and direction choosen at random
@@ -116,6 +50,12 @@
 {
  public:
   static TypeId GetTypeId (void);
+
+  enum Mode  {
+    MODE_DISTANCE,
+    MODE_TIME
+  };
+
   /**
    * Instantiate a set of RandomWalk parameters initialized
    * with construction values from \valueref{RandomWalk2dMode},
@@ -126,14 +66,6 @@
    * The default position is (0,0,0)
    */
   RandomWalk2dMobilityModel ();
-  /**
-   * \param parameters the parameters to use to control
-   * the movement of this mobile object.
-   *
-   * Create a new position object located at position (0,0,0) with
-   * the specified parameters.
-   */
-  RandomWalk2dMobilityModel (Ptr<RandomWalk2dMobilityModelParameters> parameters);
 
  private:
   void Start (void);
@@ -146,7 +78,12 @@
 
   StaticSpeedHelper m_helper;
   EventId m_event;
-  Ptr<RandomWalk2dMobilityModelParameters> m_parameters;
+  enum Mode m_mode;
+  double m_modeDistance;
+  Time m_modeTime;
+  RandomVariable m_speed;
+  RandomVariable m_direction;
+  Rectangle m_bounds;
 };
 
 
--- a/src/mobility/random-waypoint-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-waypoint-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -23,106 +23,49 @@
 #include "ns3/random-variable-default-value.h"
 #include "ns3/type-id-default-value.h"
 #include "random-waypoint-mobility-model.h"
-#include "random-position.h"
+#include "position-allocator.h"
 
 namespace ns3 {
 
 NS_OBJECT_ENSURE_REGISTERED (RandomWaypointMobilityModel);
 
-static RandomVariableDefaultValue
-g_speed ("RandomWaypointSpeed",
-	 "A random variable used to pick the speed of a random waypoint model.",
-	 "Uniform:0.3:0.7");
-
-static RandomVariableDefaultValue
-g_pause ("RandomWaypointPause",
-	 "A random variable used to pick the pause of a random waypoint model.",
-	 "Constant:2");
-
-static TypeIdDefaultValue
-g_position ("RandomWaypointPosition",
-	    "A random position model used to pick the next waypoint position.",
-	    RandomPosition::GetTypeId (),
-	    "RandomRectanglePosition");
-
-
-RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters ()
-  : m_speed (g_speed.Get ()),
-    m_pause (g_pause.Get ())
-{
-  m_position = g_position.GetValue ().CreateObject ()->GetObject<RandomPosition> ();
-}
-RandomWaypointMobilityModelParameters::RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
-									      const RandomVariable &speed,
-									      const RandomVariable &pause)
-  : m_speed (speed),
-    m_pause (pause),
-    m_position (randomPosition)
-{}
-void 
-RandomWaypointMobilityModelParameters::SetWaypointPositionModel (Ptr<RandomPosition> randomPosition)
-{
-  m_position = randomPosition;
-}
-void 
-RandomWaypointMobilityModelParameters::SetSpeed (const RandomVariable &speed)
-{
-  m_speed = speed;
-}
-void 
-RandomWaypointMobilityModelParameters::SetPause (const RandomVariable &pause)
-{
-  m_pause = pause;
-}
-void 
-RandomWaypointMobilityModelParameters::DoDispose (void)
-{
-  m_position = 0;
-}
-
-Ptr<RandomWaypointMobilityModelParameters>
-RandomWaypointMobilityModelParameters::GetCurrent (void)
-{
-  static Ptr<RandomWaypointMobilityModelParameters> parameters = 0;
-  if (parameters == 0 ||
-      g_position.IsDirty () ||
-      g_pause.IsDirty () ||
-      g_speed.IsDirty ())
-    {
-      parameters = CreateObject<RandomWaypointMobilityModelParameters> ();
-    }
-  return parameters;
-}
-
 TypeId
 RandomWaypointMobilityModel::GetTypeId (void)
 {
   static TypeId tid = TypeId ("RandomWaypointMobilityModel")
     .SetParent<MobilityModel> ()
+    .SetGroupName ("Mobility")
     .AddConstructor<RandomWaypointMobilityModel> ()
-    .AddConstructor<RandomWaypointMobilityModel,Ptr<RandomWaypointMobilityModelParameters> > ();
+    .AddAttribute ("speed",
+                   "A random variable used to pick the speed of a random waypoint model.",
+                   UniformVariable (0.3, 0.7),
+                   MakeRandomVariableAccessor (&RandomWaypointMobilityModel::m_speed),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("pause",
+                   "A random variable used to pick the pause of a random waypoint model.",
+                   ConstantVariable (2.0),
+                   MakeRandomVariableAccessor (&RandomWaypointMobilityModel::m_pause),
+                   MakeRandomVariableChecker ())
+    .AddAttribute ("position",
+                   "The position model used to pick a destination point.",
+                   Ptr<PositionAllocator> (0),
+                   MakePtrAccessor (&RandomWaypointMobilityModel::m_position),
+                   MakePtrChecker<PositionAllocator> ());
+  
   return tid;
 }
 
 RandomWaypointMobilityModel::RandomWaypointMobilityModel ()
-  : m_parameters (RandomWaypointMobilityModelParameters::GetCurrent ())
 {
   Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
 }
 
-RandomWaypointMobilityModel::RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters)
-  : m_parameters (parameters)
-{
-  Simulator::ScheduleNow (&RandomWaypointMobilityModel::Start, this);
-  NotifyCourseChange ();
-}
-
 void
 RandomWaypointMobilityModel::BeginWalk (void)
 {
   Vector m_current = m_helper.GetCurrentPosition ();
-  Vector destination = m_parameters->m_position->Get ();
-  double speed = m_parameters->m_speed.GetValue ();
+  Vector destination = m_position->GetNext ();
+  double speed = m_speed.GetValue ();
   double dx = (destination.x - m_current.x);
   double dy = (destination.y - m_current.y);
   double dz = (destination.z - m_current.z);
@@ -138,7 +81,7 @@
 void
 RandomWaypointMobilityModel::Start (void)
 {
-  Time pause = Seconds (m_parameters->m_pause.GetValue ());
+  Time pause = Seconds (m_pause.GetValue ());
   m_helper.Pause ();
   NotifyCourseChange ();
   m_event = Simulator::Schedule (pause, &RandomWaypointMobilityModel::BeginWalk, this);
--- a/src/mobility/random-waypoint-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/random-waypoint-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -23,54 +23,13 @@
 
 #include "static-speed-helper.h"
 #include "mobility-model.h"
-#include "random-position.h"
+#include "position-allocator.h"
 #include "ns3/ptr.h"
 #include "ns3/random-variable.h"
 
 namespace ns3 {
 
 /**
- * \brief the parameters which control the behavior of a random waypoint
- *        mobility model.
- */
-class RandomWaypointMobilityModelParameters : public Object
-{
-public:
-  /**
-   * Default parameters from \valueref{RandomWaypointPause},
-   * and, \valueref{RandomWaypointPosition}.
-   */
-  RandomWaypointMobilityModelParameters ();
-  /**
-   * \param randomPosition a random position model to choose the position of waypoints.
-   * \param speed a random variable to choose the speed
-   * \param pause a random variable to choose the pause delay
-   */
-  RandomWaypointMobilityModelParameters (Ptr<RandomPosition> randomPosition,
-                                         const RandomVariable &speed,
-                                         const RandomVariable &pause);
-  /**
-   * \param randomPosition a random position model to choose the position of waypoints.
-   */
-  void SetWaypointPositionModel (Ptr<RandomPosition> randomPosition);
-  /**
-   * \param speed a random variable to choose the speed
-   */
-  void SetSpeed (const RandomVariable &speed);
-  /**
-   * \param pause a random variable to choose the pause delay
-   */
-  void SetPause (const RandomVariable &pause);
-private:
-  friend class RandomWaypointMobilityModel;
-  static Ptr<RandomWaypointMobilityModelParameters> GetCurrent (void);
-  virtual void DoDispose (void);
-  RandomVariable m_speed;
-  RandomVariable m_pause;
-  Ptr<RandomPosition> m_position;
-};
-
-/**
  * \brief a random waypoint mobility model
  *
  * Each object chooses a random destination "waypoint", a random speed,
@@ -86,15 +45,7 @@
 {
 public:
   static TypeId GetTypeId (void);
-  /**
-   * Default parameters from \valueref{RandomWaypointPause},
-   * and, \valueref{RandomWaypointPosition}.
-   */
   RandomWaypointMobilityModel ();
-  /**
-   * \param parameters the parameters which control the behavior of this model.
-   */
-  RandomWaypointMobilityModel (Ptr<RandomWaypointMobilityModelParameters> parameters);
 private:
   void Start (void);
   void BeginWalk (void);
@@ -103,7 +54,9 @@
   virtual Vector DoGetVelocity (void) const;
 
   StaticSpeedHelper m_helper;
-  Ptr<RandomWaypointMobilityModelParameters> m_parameters;
+  Ptr<PositionAllocator> m_position;
+  RandomVariable m_speed;
+  RandomVariable m_pause;
   EventId m_event;
 };
 
--- a/src/mobility/rectangle.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/rectangle.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -20,8 +20,10 @@
 #include "rectangle.h"
 #include "vector.h"
 #include "ns3/assert.h"
+#include "ns3/fatal-error.h"
 #include <cmath>
 #include <algorithm>
+#include <sstream> 
 
 namespace ns3 {
 
@@ -117,5 +119,27 @@
 
 }
 
+VALUE_HELPER_CPP (Rectangle);
+
+std::ostream &
+operator << (std::ostream &os, const Rectangle &rectangle)
+{
+  os << rectangle.xMin << "|" << rectangle.xMax << "|" << rectangle.yMin << "|" << rectangle.yMax;
+  return os;
+}
+std::istream &
+operator >> (std::istream &is, Rectangle &rectangle)
+ {
+  char c1, c2, c3;
+  is >> rectangle.xMin >> c1 >> rectangle.xMax >> c2 >> rectangle.yMin >> c3 >> rectangle.yMax;
+  if (c1 != '|' ||
+      c2 != '|' ||
+      c3 != '|')
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  return is;
+}
+
 
 } // namespace ns3
--- a/src/mobility/rectangle.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/rectangle.h	Wed Feb 27 22:19:39 2008 +0100
@@ -20,6 +20,9 @@
 #ifndef RECTANGLE_H
 #define RECTANGLE_H
 
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
+
 namespace ns3 {
 
 class Vector;
@@ -58,8 +61,15 @@
   double xMax;
   double yMin;
   double yMax;
+
+  VALUE_HELPER_HEADER_1 (Rectangle);
 };
 
+std::ostream &operator << (std::ostream &os, const Rectangle &rectangle);
+std::istream &operator >> (std::istream &is, Rectangle &rectangle);
+
+VALUE_HELPER_HEADER_2 (Rectangle);
+
 } // namespace ns3
 
 #endif /* RECTANGLE_H */
--- a/src/mobility/static-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/static-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -29,15 +29,12 @@
   static TypeId tid = TypeId ("StaticMobilityModel")
     .SetParent<MobilityModel> ()
     .AddConstructor<StaticMobilityModel> ()
-    .AddConstructor<StaticMobilityModel,const Vector &> ();
+    ;
   return tid;
 }
   
 StaticMobilityModel::StaticMobilityModel ()
 {}
-StaticMobilityModel::StaticMobilityModel (const Vector &position)
-  : m_position (position)
-{}
 StaticMobilityModel::~StaticMobilityModel ()
 {}
 
--- a/src/mobility/static-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/static-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -21,6 +21,7 @@
 #define STATIC_MOBILITY_MODEL_H
 
 #include "mobility-model.h"
+#include "vector.h"
 
 namespace ns3 {
 
@@ -37,13 +38,6 @@
    * Create a position located at coordinates (0,0,0)
    */
   StaticMobilityModel ();
-  /**
-   * \param position the initial position.
-   *
-   * Create a position located at coordinates (x,y,z).
-   * Unit is meters
-   */
-  StaticMobilityModel (const Vector &position);
   virtual ~StaticMobilityModel ();
 
 private:
--- a/src/mobility/static-speed-mobility-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/static-speed-mobility-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -28,21 +28,12 @@
 {
   static TypeId tid = TypeId ("StaticSpeedMobilityModel")
     .SetParent<MobilityModel> ()
-    .AddConstructor<StaticSpeedMobilityModel> ()
-    .AddConstructor<StaticSpeedMobilityModel,const Vector &> ()
-    .AddConstructor<StaticSpeedMobilityModel,const Vector &,const Vector &> ();
+    .AddConstructor<StaticSpeedMobilityModel> ();
   return tid;
 }
 
 StaticSpeedMobilityModel::StaticSpeedMobilityModel ()
 {}
-StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Vector &position)
-  : m_helper (position)
-{}
-StaticSpeedMobilityModel::StaticSpeedMobilityModel (const Vector &position,
-                                                    const Vector &speed)
-  : m_helper (position, speed)
-{}
 
 StaticSpeedMobilityModel::~StaticSpeedMobilityModel ()
 {}
--- a/src/mobility/static-speed-mobility-model.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/static-speed-mobility-model.h	Wed Feb 27 22:19:39 2008 +0100
@@ -41,19 +41,6 @@
    * speed (0,0,0).
    */
   StaticSpeedMobilityModel ();
-  /**
-   * Create a position located at coordinates (x,y,z) with
-   * speed (0,0,0).
-   */
-  StaticSpeedMobilityModel (const Vector &position);
-  /**
-   *
-   * Create a position located at coordinates (x,y,z) with
-   * speed (dx,dy,dz).
-   * Unit is meters and meters/s
-   */
-  StaticSpeedMobilityModel (const Vector &position,
-                            const Vector &speed);
   virtual ~StaticSpeedMobilityModel ();
 
   /**
--- a/src/mobility/vector.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/vector.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -18,10 +18,14 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 #include "vector.h"
+#include "ns3/fatal-error.h"
 #include <cmath>
+#include <sstream>
 
 namespace ns3 {
 
+VALUE_HELPER_CPP (Vector);
+
 
 Vector::Vector (double _x, double _y, double _z)
   : x (_x),
@@ -45,4 +49,21 @@
   return distance;
 }
 
+std::ostream &operator << (std::ostream &os, const Vector &vector)
+{
+  os << vector.x << ":" << vector.y << ":" << vector.z;
+  return os;
+}
+std::istream &operator >> (std::istream &is, Vector &vector)
+{
+  char c1, c2;
+  is >> vector.x >> c1 >> vector.y >> c2 >> vector.z;
+  if (c1 != ':' ||
+      c2 != ':')
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  return is;
+}
+
 } // namespace ns3
--- a/src/mobility/vector.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/vector.h	Wed Feb 27 22:19:39 2008 +0100
@@ -20,6 +20,9 @@
 #ifndef VECTOR_H
 #define VECTOR_H
 
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
+
 namespace ns3 {
 
 /**
@@ -54,10 +57,17 @@
    * z coordinate of vector vector
    */
   double z;
+
+  VALUE_HELPER_HEADER_1 (Vector);
 };
 
 double CalculateDistance (const Vector &a, const Vector &b);
 
+VALUE_HELPER_HEADER_2 (Vector);
+
+std::ostream &operator << (std::ostream &os, const Vector &vector);
+std::istream &operator >> (std::istream &is, Vector &vector);
+
 } // namespace ns3
 
 #endif /* VECTOR_H */
--- a/src/mobility/wscript	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/mobility/wscript	Wed Feb 27 22:19:39 2008 +0100
@@ -4,12 +4,10 @@
     mobility = bld.create_ns3_module('mobility', ['core', 'simulator'])
     mobility.source = [
         'vector.cc',
-        'grid-topology.cc',
         'hierarchical-mobility-model.cc',
         'mobility-model.cc',
         'mobility-model-notifier.cc',
-        'random-position.cc',
-        'random-topology.cc',
+        'position-allocator.cc',
         'rectangle.cc',
         'rectangle-default-value.cc',
         'static-mobility-model.cc',
@@ -18,18 +16,17 @@
         'random-waypoint-mobility-model.cc',
         'random-walk-2d-mobility-model.cc',
         'random-direction-2d-mobility-model.cc',
-        'ns2-mobility-file-topology.cc',
+        'ns2-mobility-helper.cc',
+        'mobility-helper.cc',
         ]
 
     headers = bld.create_obj('ns3header')
     headers.source = [
         'vector.h',
-        'grid-topology.h',
         'hierarchical-mobility-model.h',
         'mobility-model.h',
         'mobility-model-notifier.h',
-        'random-position.h',
-        'random-topology.h',
+        'position-allocator.h',
         'rectangle.h',
         'rectangle-default-value.h',
         'static-mobility-model.h',
@@ -38,5 +35,6 @@
         'random-waypoint-mobility-model.h',
         'random-walk-2d-mobility-model.h',
         'random-direction-2d-mobility-model.h',
-        'ns2-mobility-file-topology.h',
+        'ns2-mobility-helper.h',
+        'mobility-helper.h',
         ]
--- a/src/node/address.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/address.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -107,6 +107,8 @@
   return type;
 }
 
+VALUE_HELPER_CPP (Address);
+
 bool operator == (const Address &a, const Address &b)
 {
   NS_ASSERT (a.m_type == b.m_type || 
@@ -159,6 +161,12 @@
   return os;
 }
 
+std::istream& operator>> (std::istream& is, Address & address)
+{
+  // XXX: need to be able to parse this.
+  return is;
+}
+
 
 
 } // namespace ns3
--- a/src/node/address.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/address.h	Wed Feb 27 22:19:39 2008 +0100
@@ -3,6 +3,8 @@
 
 #include <stdint.h>
 #include <ostream>
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
 
 namespace ns3 {
 
@@ -151,6 +153,8 @@
    * \returns a new type id.
    */
   static uint8_t Register (void);
+
+  VALUE_HELPER_HEADER_1 (Address);
 private:
   friend bool operator == (const Address &a, const Address &b);
   friend bool operator < (const Address &a, const Address &b);
@@ -161,12 +165,15 @@
   uint8_t m_data[MAX_SIZE];
 };
 
+VALUE_HELPER_HEADER_2 (Address);
+
 bool operator == (const Address &a, const Address &b);
 bool operator != (const Address &a, const Address &b);
 bool operator < (const Address &a, const Address &b);
 std::ostream& operator<< (std::ostream& os, const Address & address);
+std::istream& operator>> (std::istream& is, Address & address);
+
 
 } // namespace ns3
 
-
 #endif /* ADDRESS_H */
--- a/src/node/application.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/application.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -31,14 +31,26 @@
 
 namespace ns3 {
 
+NS_OBJECT_ENSURE_REGISTERED (Application);
+
 // Application Methods
 
+TypeId 
+Application::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("Application")
+    .SetParent<Object> ()
+    .AddAttribute ("Node", "The on which this application resides",
+                   Ptr<Node> (0),
+                   MakePtrAccessor (&Application::m_node),
+                   MakePtrChecker<Node> ())
+    ;
+  return tid;
+}
+
 // \brief Application Constructor
-Application::Application(Ptr<Node> n) 
-    : m_node (n)
-{
-  m_node->AddApplication (this);
-}
+Application::Application()
+{}
   
 // \brief Application Destructor
 Application::~Application()
--- a/src/node/application.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/application.h	Wed Feb 27 22:19:39 2008 +0100
@@ -52,7 +52,8 @@
 class Application : public Object
 {
 public:
-  Application(Ptr<Node>);
+  static TypeId GetTypeId (void);
+  Application();
   virtual ~Application();
   
   /**
--- a/src/node/drop-tail-queue.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/drop-tail-queue.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -18,6 +18,7 @@
  */
 
 #include "ns3/log.h"
+#include "ns3/uinteger.h"
 #include "drop-tail-queue.h"
 
 NS_LOG_COMPONENT_DEFINE ("DropTailQueue");
@@ -30,14 +31,19 @@
 {
   static TypeId tid = TypeId ("DropTailQueue")
     .SetParent<Queue> ()
-    .AddConstructor<DropTailQueue> ();
+    .AddConstructor<DropTailQueue> ()
+    .AddAttribute ("MaxPackets", "The maximum number of packets accepted by this DropTailQueue.",
+                   Uinteger (100),
+                   MakeUintegerAccessor (&DropTailQueue::m_maxPackets),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
+  
   return tid;
 }
 
 DropTailQueue::DropTailQueue () :
   Queue (),
-  m_packets (),
-  m_maxPackets(DTQ_NPACKETS_MAX_DEFAULT)
+  m_packets ()
 {
   NS_LOG_FUNCTION;
 }
@@ -47,22 +53,6 @@
   NS_LOG_FUNCTION;
 }
 
-void 
-DropTailQueue::SetMaxPackets (uint32_t npackets)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_PARAMS (this << npackets);
-  m_maxPackets = npackets;
-}
-
-uint32_t 
-DropTailQueue::GetMaxPackets (void)
-{
-  NS_LOG_FUNCTION;
-  NS_LOG_LOGIC ("returns " << m_maxPackets);
-  return m_maxPackets;
-}
-
 bool 
 DropTailQueue::DoEnqueue (Ptr<Packet> p)
 {
@@ -142,8 +132,8 @@
 {
   bool result = true;
 
-  DropTailQueue queue;
-  queue.SetMaxPackets (3);
+  Ptr<DropTailQueue> queue = CreateObject<DropTailQueue> ();
+  NS_TEST_ASSERT (queue->SetAttribute ("MaxPackets", Uinteger (3)));
   
   Ptr<Packet> p1, p2, p3, p4;
   p1 = Create<Packet> ();
@@ -151,34 +141,34 @@
   p3 = Create<Packet> ();
   p4 = Create<Packet> ();
 
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 0);
-  queue.Enqueue (p1);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 1);
-  queue.Enqueue (p2);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 2);
-  queue.Enqueue (p3);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 3);
-  queue.Enqueue (p4); // will be dropped
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 3);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 0);
+  queue->Enqueue (p1);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 1);
+  queue->Enqueue (p2);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 2);
+  queue->Enqueue (p3);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 3);
+  queue->Enqueue (p4); // will be dropped
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 3);
 
   Ptr<Packet> p;
 
-  p = queue.Dequeue ();
+  p = queue->Dequeue ();
   NS_TEST_ASSERT (p != 0);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 2);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 2);
   NS_TEST_ASSERT_EQUAL (p->GetUid (), p1->GetUid ());
 
-  p = queue.Dequeue ();
+  p = queue->Dequeue ();
   NS_TEST_ASSERT (p != 0);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 1);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 1);
   NS_TEST_ASSERT_EQUAL (p->GetUid (), p2->GetUid ());
 
-  p = queue.Dequeue ();
+  p = queue->Dequeue ();
   NS_TEST_ASSERT (p != 0);
-  NS_TEST_ASSERT_EQUAL (queue.GetNPackets (), 0);
+  NS_TEST_ASSERT_EQUAL (queue->GetNPackets (), 0);
   NS_TEST_ASSERT_EQUAL (p->GetUid (), p3->GetUid ());
 
-  p = queue.Dequeue ();
+  p = queue->Dequeue ();
   NS_TEST_ASSERT (p == 0);
 
   return result;
--- a/src/node/drop-tail-queue.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/drop-tail-queue.h	Wed Feb 27 22:19:39 2008 +0100
@@ -28,8 +28,6 @@
 
 class TraceContainer;
 
-const int DTQ_NPACKETS_MAX_DEFAULT = 100;
-
 /**
  * \brief A FIFO packet queue that drops tail-end packets on overflow
  */
@@ -44,16 +42,6 @@
   DropTailQueue ();
 
   virtual ~DropTailQueue();
-  /**
-   * \param npackets The maximum number of packets this queue will hold before
-   * dropping packets.
-   */
-  void SetMaxPackets (uint32_t npackets);
-  /**
-   * \return The maximum number of packets this queue will hold before dropping
-   * packets.
-   */
-  uint32_t GetMaxPackets (void);
 
 private:
   virtual bool DoEnqueue (Ptr<Packet> p);
--- a/src/node/ipv4-address.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/ipv4-address.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -301,6 +301,21 @@
   mask.Print (os);
   return os;
 }
+std::istream & operator >> (std::istream &is, Ipv4Address &address)
+{
+  std::string str;
+  is >> str;
+  address = Ipv4Address (str.c_str ());
+  return is;
+}
+std::istream & operator >> (std::istream &is, Ipv4Mask &mask)
+{
+  std::string str;
+  is >> str;
+  mask = Ipv4Mask (str.c_str ());
+  return is;
+}
+
 bool operator == (Ipv4Mask const &a, Ipv4Mask const &b)
 {
   return a.IsEqual (b);
@@ -310,5 +325,7 @@
   return !a.IsEqual (b);
 }
 
+VALUE_HELPER_CPP (Ipv4Address);
+VALUE_HELPER_CPP (Ipv4Mask);
 
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/ipv4-address.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/ipv4-address.h	Wed Feb 27 22:19:39 2008 +0100
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include <ostream>
 #include "address.h"
+#include "ns3/attribute-helper.h"
 
 namespace ns3 {
 
@@ -141,6 +142,8 @@
   static Ipv4Address GetAny (void);
   static Ipv4Address GetBroadcast (void);
   static Ipv4Address GetLoopback (void);
+
+  VALUE_HELPER_HEADER_1 (Ipv4Address);
 private:
   Address ConvertTo (void) const;
   static uint8_t GetType (void);
@@ -177,12 +180,19 @@
 
   static Ipv4Mask GetLoopback (void);
   static Ipv4Mask GetZero (void);
+
+  VALUE_HELPER_HEADER_1 (Ipv4Mask);
 private:
   uint32_t m_mask;
 };
 
+VALUE_HELPER_HEADER_2 (Ipv4Address);
+VALUE_HELPER_HEADER_2 (Ipv4Mask);
+
 std::ostream& operator<< (std::ostream& os, Ipv4Address const& address);
 std::ostream& operator<< (std::ostream& os, Ipv4Mask const& mask);
+std::istream & operator >> (std::istream &is, Ipv4Address &address);
+std::istream & operator >> (std::istream &is, Ipv4Mask &mask);
 
 inline bool operator == (const Ipv4Address &a, const Ipv4Address &b)
 {
@@ -206,6 +216,6 @@
 bool operator == (Ipv4Mask const &a, Ipv4Mask const &b);
 bool operator != (Ipv4Mask const &a, Ipv4Mask const &b);
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* IPV4_ADDRESS_H */
--- a/src/node/mac48-address.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/mac48-address.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -25,6 +25,8 @@
 
 namespace ns3 {
 
+VALUE_HELPER_CPP (Mac48Address);
+
 #define ASCII_a (0x41)
 #define ASCII_z (0x5a)
 #define ASCII_A (0x61)
@@ -149,6 +151,7 @@
   static Mac48Address broadcast = Mac48Address ("ff:ff:ff:ff:ff:ff");
   return broadcast;
 }
+
 bool operator == (const Mac48Address &a, const Mac48Address &b)
 {
   return memcmp (a.m_address, b.m_address, 6) == 0;
@@ -197,5 +200,11 @@
   return os;
 }
 
+std::istream& operator>> (std::istream& is, const Mac48Address & address)
+{
+  // XXX !
+  return is;
+}
+
 
 } // namespace ns3
--- a/src/node/mac48-address.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/mac48-address.h	Wed Feb 27 22:19:39 2008 +0100
@@ -17,11 +17,13 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#ifndef EUI48_ADDRESS_H
-#define EUI48_ADDRESS_H
+#ifndef MAC48_ADDRESS_H
+#define MAC48_ADDRESS_H
 
 #include <stdint.h>
 #include <ostream>
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
 
 namespace ns3 {
 
@@ -93,6 +95,8 @@
    * \returns the broadcast address
    */
   static Mac48Address GetBroadcast (void);
+
+  VALUE_HELPER_HEADER_1 (Mac48Address);
 private:
   /**
    * \returns a new Address instance
@@ -107,11 +111,14 @@
   uint8_t m_address[6];
 };
 
+VALUE_HELPER_HEADER_2 (Mac48Address);
+
 bool operator == (const Mac48Address &a, const Mac48Address &b);
 bool operator != (const Mac48Address &a, const Mac48Address &b);
 bool operator < (const Mac48Address &a, const Mac48Address &b);
 std::ostream& operator<< (std::ostream& os, const Mac48Address & address);
+std::istream& operator>> (std::istream& is, const Mac48Address & address);
 
 } // namespace ns3
 
-#endif /* EUI48_ADDRESS_H */
+#endif /* MAC48_ADDRESS_H */
--- a/src/node/mac64-address.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/mac64-address.h	Wed Feb 27 22:19:39 2008 +0100
@@ -17,8 +17,8 @@
  *
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
-#ifndef EUI64_ADDRESS_H
-#define EUI64_ADDRESS_H
+#ifndef MAC64_ADDRESS_H
+#define MAC64_ADDRESS_H
 
 #include <stdint.h>
 #include <ostream>
@@ -95,4 +95,4 @@
 
 } // namespace ns3
 
-#endif /* EUI64_ADDRESS_H */
+#endif /* MAC64_ADDRESS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/net-device-container.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,40 @@
+#include "net-device-container.h"
+
+namespace ns3 {
+
+NetDeviceContainer::Iterator 
+NetDeviceContainer::Begin (void) const
+{
+  return m_nodes.begin ();
+}
+NetDeviceContainer::Iterator 
+NetDeviceContainer::End (void) const
+{
+  return m_nodes.end ();
+}
+
+uint32_t 
+NetDeviceContainer::GetN (void) const
+{
+  return m_nodes.size ();
+}
+Ptr<NetDevice> 
+NetDeviceContainer::Get (uint32_t i) const
+{
+  return m_nodes[i];
+}
+void 
+NetDeviceContainer::Add (NetDeviceContainer other)
+{
+  for (Iterator i = other.Begin (); i != other.End (); i++)
+    {
+      m_nodes.push_back (*i);
+    }
+}
+void 
+NetDeviceContainer::Add (Ptr<NetDevice> node)
+{
+  m_nodes.push_back (node);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/net-device-container.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,31 @@
+#ifndef NET_DEVICE_CONTAINER_H
+#define NET_DEVICE_CONTAINER_H
+
+#include <stdint.h>
+#include <vector>
+#include "net-device.h"
+
+namespace ns3 {
+
+class NetDeviceContainer
+{
+public:
+  typedef std::vector<Ptr<NetDevice> >::const_iterator Iterator;
+
+  Iterator Begin (void) const;
+  Iterator End (void) const;
+
+  uint32_t GetN (void) const;
+  Ptr<NetDevice> Get (uint32_t i) const;
+
+  void Create (uint32_t n);
+  void Add (NetDeviceContainer other);
+  void Add (Ptr<NetDevice> node);
+
+private:
+  std::vector<Ptr<NetDevice> > m_nodes;
+};
+
+} // namespace ns3
+
+#endif /* NET_DEVICE_CONTAINER_H */
--- a/src/node/net-device.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/net-device.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -19,15 +19,9 @@
  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
  */
 
-#include <iostream>
-#include "ns3/assert.h"
 #include "ns3/object.h"
 #include "ns3/log.h"
-#include "ns3/trace-resolver.h"
-#include "ns3/packet.h"
-#include "channel.h"
 #include "net-device.h"
-#include "node.h"
 
 NS_LOG_COMPONENT_DEFINE ("NetDevice");
 
@@ -42,272 +36,7 @@
   return tid;
 }
 
-NetDevice::NetDevice(Ptr<Node> node, const Address& addr) : 
-  m_node (node), 
-  m_name(""), 
-  m_ifIndex (0), 
-  m_address (addr),
-  m_mtu (0xffff), 
-  m_isUp (false), 
-  m_isBroadcast (false), 
-  m_isMulticast (false), 
-  m_isPointToPoint (false)
-{
-  NS_LOG_FUNCTION;
-  m_node->AddDevice (this);
-}
-
 NetDevice::~NetDevice ()
-{
-  NS_LOG_FUNCTION;
-}
-
-Address 
-NetDevice::GetAddress (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_address;
-}
-
-bool
-NetDevice::SetMtu (const uint16_t mtu) 
-{
-  NS_LOG_FUNCTION;
-  m_mtu = mtu;
-  return true;
-}
-
-uint16_t 
-NetDevice::GetMtu (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_mtu;
-}
-
-void
-NetDevice::SetName(const std::string name) 
-{ 
-  NS_LOG_FUNCTION;
-  m_name = name; 
-}
-
-std::string 
-NetDevice::GetName(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_name; 
-}
-
-void
-NetDevice::SetIfIndex(uint32_t index) 
-{ 
-  NS_LOG_FUNCTION;
-  m_ifIndex = index; 
-}
-
-uint32_t
-NetDevice::GetIfIndex(void) const 
-{ 
-  NS_LOG_FUNCTION;
-  return m_ifIndex; 
-}
-
-bool 
-NetDevice::IsLinkUp (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isUp;
-}
-
-void 
-NetDevice::SetLinkChangeCallback (Callback<void> callback)
-{
-  NS_LOG_FUNCTION;
-  m_linkChangeCallback = callback;
-}
-
-bool
-NetDevice::IsBroadcast (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isBroadcast;
-}
-
-Address const &
-NetDevice::GetBroadcast (void) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT (m_isBroadcast);
-  return m_broadcast;
-}
-
-void
-NetDevice::EnableBroadcast (Address broadcast)
-{
-  NS_LOG_FUNCTION;
-  m_isBroadcast = true;
-  m_broadcast = broadcast;
-}
-
-void
-NetDevice::DisableBroadcast (void)
-{
-  NS_LOG_FUNCTION;
-  m_isBroadcast = false;
-}
-
-bool
-NetDevice::IsMulticast (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isMulticast;
-}
-
-Address 
-NetDevice::GetMulticast (void) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
-    "Invalid operation when not IsMulticast ()");
-  return m_multicast;
-}
+{}
 
-Address
-NetDevice::MakeMulticastAddress(Ipv4Address multicastGroup) const
-{
-  NS_LOG_FUNCTION;
-  NS_ASSERT_MSG (m_isMulticast, "NetDevice::GetMulticast (): "
-    "Invalid operation when not IsMulticast ()");
-  return m_multicast;
-}
-
-void
-NetDevice::EnableMulticast (Address multicast)
-{
-  NS_LOG_FUNCTION;
-  m_isMulticast = true;
-  m_multicast = multicast;
-}
-
-void
-NetDevice::DisableMulticast (void)
-{
-  NS_LOG_FUNCTION;
-  m_isMulticast = false;
-}
-
-bool
-NetDevice::IsPointToPoint (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_isPointToPoint;
-}
-
-void
-NetDevice::EnablePointToPoint (void)
-{
-  NS_LOG_FUNCTION;
-  m_isPointToPoint = true;
-}
-
-void
-NetDevice::DisablePointToPoint (void)
-{
-  NS_LOG_FUNCTION;
-  m_isPointToPoint = false;
-}
-
-// Receive packet from above
-bool 
-NetDevice::Send(Ptr<Packet> p, const Address& dest, uint16_t protocolNumber)
-{
-  NS_LOG_FUNCTION;
-  if (m_isUp)
-    {
-      return SendTo(p, dest, protocolNumber);
-    }
-  else
-    {
-      return false;
-    }
-}
-
-Ptr<Channel>
-NetDevice::GetChannel (void) const
-{
-  NS_LOG_FUNCTION;
-  return DoGetChannel ();
-}
-
-// Receive packets from below
-bool
-NetDevice::ForwardUp(Ptr<Packet> p, uint16_t param, const Address &from)
-{
-  NS_LOG_FUNCTION;
-  bool retval = false;
-
-  NS_LOG_LOGIC ("UID is " << p->GetUid() << " device is: " << GetName());
-  
-  if (!m_receiveCallback.IsNull ())
-    {
-      retval = m_receiveCallback (this, p, param, from);
-    } 
-  else 
-    {
-      NS_LOG_WARN ("NetDevice::Receive call back is NULL");
-    }
-
-    return retval;
-}
-
-void 
-NetDevice::NotifyLinkUp (void)
-{
-  NS_LOG_FUNCTION;
-  m_isUp = true;
-  if (!m_linkChangeCallback.IsNull ())
-    {
-      m_linkChangeCallback ();
-    }
-}
-
-void 
-NetDevice::NotifyLinkDown (void)
-{
-  NS_LOG_FUNCTION;
-  m_isUp = false;
-  if (!m_linkChangeCallback.IsNull ())
-    {
-      m_linkChangeCallback ();
-    }
-}
-
-Ptr<Node>
-NetDevice::GetNode (void) const
-{
-  NS_LOG_FUNCTION;
-  return m_node;
-}
-
-bool
-NetDevice::NeedsArp (void) const
-{
-  NS_LOG_FUNCTION;
-  return DoNeedsArp ();
-}
-
-void 
-NetDevice::SetReceiveCallback (ReceiveCallback cb)
-{
-  NS_LOG_FUNCTION;
-  m_receiveCallback = cb;
-}
-
-void
-NetDevice::DoDispose()
-{
-  NS_LOG_FUNCTION;
-  m_node = 0;
-}
-
-}; // namespace ns3
+} // namespace ns3
--- a/src/node/net-device.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/net-device.h	Wed Feb 27 22:19:39 2008 +0100
@@ -63,52 +63,53 @@
   static TypeId GetTypeId (void);
   virtual ~NetDevice();
 
+  /**
+   * \param name name of the device (e.g. "eth0")
+   */
+  virtual void SetName(const std::string name) = 0;
+  /**
+   * \return name name of the device (e.g. "eth0")
+   */
+  virtual std::string GetName(void) const = 0;
+  /**
+   * \param index ifIndex of the device 
+   */
+  virtual void SetIfIndex(const uint32_t index) = 0;
+  /**
+   * \return index ifIndex of the device 
+   */
+  virtual uint32_t GetIfIndex(void) const = 0;
+
 
   /**
    * \return the channel this NetDevice is connected to. The value
    *         returned can be zero if the NetDevice is not yet connected
    *         to any channel.
    */
-  Ptr<Channel> GetChannel (void) const;
+  virtual Ptr<Channel> GetChannel (void) const = 0;
 
   /**
    * \return the current Address of this interface.
    */
-  Address GetAddress (void) const;
+  virtual Address GetAddress (void) const = 0;
   /**
    * \param mtu MTU value, in bytes, to set for the device
    * \return whether the MTU value was within legal bounds
    * 
    * Override for default MTU defined on a per-type basis.
    */
-  bool SetMtu (const uint16_t mtu);
+  virtual bool SetMtu (const uint16_t mtu) = 0;
   /**
    * \return the link-level MTU in bytes for this interface.
    * 
    * This value is typically used by the IP layer to perform
    * IP fragmentation when needed.
    */
-  uint16_t GetMtu (void) const;
-  /**
-   * \param name name of the device (e.g. "eth0")
-   */
-  void SetName(const std::string name); 
-  /**
-   * \return name name of the device (e.g. "eth0")
-   */
-  std::string GetName(void) const;
-  /**
-   * \param index ifIndex of the device 
-   */
-  void SetIfIndex(const uint32_t index);
-  /**
-   * \return index ifIndex of the device 
-   */
-  uint32_t GetIfIndex(void) const;
+  virtual uint16_t GetMtu (void) const = 0;
   /**
    * \return true if link is up; false otherwise
    */
-  bool IsLinkUp (void) const;
+  virtual bool IsLinkUp (void) const = 0;
   /**
    * \param callback the callback to invoke
    *
@@ -117,12 +118,12 @@
    * by the IP/ARP layer to flush the ARP cache 
    * whenever the link goes up.
    */
-  void SetLinkChangeCallback (Callback<void> callback);
+  virtual void SetLinkChangeCallback (Callback<void> callback) = 0;
   /**
    * \return true if this interface supports a broadcast address,
    *         false otherwise.
    */
-  bool IsBroadcast (void) const;
+  virtual bool IsBroadcast (void) const = 0;
   /**
    * \return the broadcast address supported by
    *         this netdevice.
@@ -130,12 +131,12 @@
    * Calling this method is invalid if IsBroadcast returns
    * not true.
    */
-  Address const &GetBroadcast (void) const;
+  virtual Address GetBroadcast (void) const = 0;
 
   /**
    * \return value of m_isMulticast flag
    */
-  bool IsMulticast (void) const;
+  virtual bool IsMulticast (void) const = 0;
 
   /**
    * \brief Return the MAC multicast base address used when mapping multicast
@@ -160,8 +161,8 @@
    * The method NS_ASSERTs if the device is not a multicast device.
    * \see NetDevice::MakeMulticastAddress
    */
-  Address GetMulticast (void) const;
-
+  virtual Address GetMulticast (void) const = 0;
+  
   /**
    * \brief Make and return a MAC multicast address using the provided
    *        multicast group
@@ -192,12 +193,12 @@
    * \see Address
    * \see NetDevice::IsMulticast
    */
-  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const;
-
+  virtual Address MakeMulticastAddress (Ipv4Address multicastGroup) const = 0;
+  
   /**
    * \return value of m_isPointToPoint flag
    */
-  bool IsPointToPoint (void) const;
+  virtual bool IsPointToPoint (void) const = 0;
   /**
    * \param packet packet sent from above down to Network Device
    * \param dest mac address of the destination (already resolved)
@@ -210,7 +211,7 @@
    * 
    * \return whether the Send operation succeeded 
    */
-  bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber);
+  virtual bool Send(Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber) = 0;
   /**
    * \returns the node base class which contains this network
    *          interface.
@@ -219,7 +220,7 @@
    * base class to print the nodeid for example, it can invoke
    * this method.
    */
-  Ptr<Node> GetNode (void) const;
+  virtual Ptr<Node> GetNode (void) const = 0;
 
   /**
    * \returns true if ARP is needed, false otherwise.
@@ -227,7 +228,7 @@
    * Called by higher-layers to check if this NetDevice requires
    * ARP to be used.
    */
-  bool NeedsArp (void) const;
+  virtual bool NeedsArp (void) const = 0;
 
   /**
    * \param device a pointer to the net device which is calling this callback
@@ -246,116 +247,10 @@
    *        be forwarded to the higher layers.
    *
    */
-  void SetReceiveCallback (ReceiveCallback cb);
-
- protected:
-  /**
-   * \param node base class node pointer of device's node 
-   * \param addr MAC address of this device.
-   */
-  NetDevice(Ptr<Node> node, const Address& addr);
-  /**
-   * Enable broadcast support. This method should be
-   * called by subclasses from their constructor
-   */
-  void EnableBroadcast (Address broadcast);
-  /**
-   * Set m_isBroadcast flag to false
-   */
-  void DisableBroadcast (void);
-  /**
-   * Enable multicast support. This method should be
-   * called by subclasses from their constructor
-   */
-  void EnableMulticast (Address multicast);
-  /**
-   * Set m_isMulticast flag to false
-   */
-  void DisableMulticast (void);
-  /**
-   * Set m_isPointToPoint flag to true
-   */
-  void EnablePointToPoint (void);
-  /**
-   * Set m_isPointToPoint flag to false
-   */
-  void DisablePointToPoint (void);
-  /**
-   * When a subclass notices that the link status has changed to up,
-   * it notifies its parent class by calling this method. This method
-   * is responsible for notifying any LinkUp callbacks. 
-   */
-  void NotifyLinkUp (void);
-  /**
-   * When a subclass notices that the link status has changed to 
-   * down, it notifies its parent class by calling this method.
-   */
-  void NotifyLinkDown (void);
+  virtual void SetReceiveCallback (ReceiveCallback cb) = 0;
 
-  /**
-   * \param p packet sent from below up to Network Device
-   * \param param Extra parameter extracted from header and needed by
-   * some protocols
-   * \param address the address of the sender of this packet.
-   * \returns true if the packet was forwarded successfully,
-   *          false otherwise.
-   *
-   * When a subclass gets a packet from the channel, it 
-   * forwards it to the higher layers by calling this method
-   * which is responsible for passing it up to the Rx callback.
-   */
-  bool ForwardUp (Ptr<Packet> p, uint16_t param, const Address &address);
-
-
-  /**
-   * The dispose method for this NetDevice class.
-   * Subclasses are expected to override this method _and_
-   * to chain up to it by calling NetDevice::DoDispose
-   * at the end of their own DoDispose method.
-   */
-  virtual void DoDispose (void);
-
- private:
-  /**
-   * \param p packet to send
-   * \param dest address of destination to which packet must be sent
-   * \param protocolNumber Number of the protocol (used with some protocols)
-   * \returns true if the packet could be sent successfully, false
-   *          otherwise.
-   *
-   * This is the private virtual target function of the public Send()
-   * method.  When the link is Up, this method is invoked to ask 
-   * subclasses to forward packets. Subclasses MUST override this method.
-   */
-  virtual bool SendTo (Ptr<Packet> p, const Address &dest, uint16_t protocolNumber) = 0;
-  /**
-   * \returns true if this NetDevice needs the higher-layers
-   *          to perform ARP over it, false otherwise.
-   *
-   * Subclasses must implement this method.
-   */
-  virtual bool DoNeedsArp (void) const = 0;
-  /**
-   * \returns the channel associated to this NetDevice.
-   *
-   * Subclasses must implement this method.
-   */
-  virtual Ptr<Channel> DoGetChannel (void) const = 0;
-
-  Ptr<Node>     m_node;
-  std::string   m_name;
-  uint16_t      m_ifIndex;
-  Address       m_address;
-  Address       m_broadcast;
-  Address       m_multicast;
-  uint16_t      m_mtu;
-  bool          m_isUp;
-  bool          m_isBroadcast;
-  bool          m_isMulticast;
-  bool          m_isPointToPoint;
-  Callback<void> m_linkChangeCallback;
-  ReceiveCallback m_receiveCallback;
 };
 
-}; // namespace ns3
-#endif
+} // namespace ns3
+
+#endif /* NET_DEVICE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/node-container.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,48 @@
+#include "node-container.h"
+
+namespace ns3 {
+
+NodeContainer::Iterator 
+NodeContainer::Begin (void) const
+{
+  return m_nodes.begin ();
+}
+NodeContainer::Iterator 
+NodeContainer::End (void) const
+{
+  return m_nodes.end ();
+}
+
+uint32_t 
+NodeContainer::GetN (void) const
+{
+  return m_nodes.size ();
+}
+Ptr<Node> 
+NodeContainer::Get (uint32_t i) const
+{
+  return m_nodes[i];
+}
+void 
+NodeContainer::Create (uint32_t n)
+{
+  for (uint32_t i = 0; i < n; i++)
+    {
+      m_nodes.push_back (CreateObject<Node> ());
+    }
+}
+void 
+NodeContainer::Add (NodeContainer other)
+{
+  for (Iterator i = other.Begin (); i != other.End (); i++)
+    {
+      m_nodes.push_back (*i);
+    }
+}
+void 
+NodeContainer::Add (Ptr<Node> node)
+{
+  m_nodes.push_back (node);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/node/node-container.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,31 @@
+#ifndef NODE_CONTAINER_H
+#define NODE_CONTAINER_H
+
+#include <stdint.h>
+#include <vector>
+#include "node.h"
+
+namespace ns3 {
+
+class NodeContainer
+{
+public:
+  typedef std::vector<Ptr<Node> >::const_iterator Iterator;
+
+  Iterator Begin (void) const;
+  Iterator End (void) const;
+
+  uint32_t GetN (void) const;
+  Ptr<Node> Get (uint32_t i) const;
+
+  void Create (uint32_t n);
+  void Add (NodeContainer other);
+  void Add (Ptr<Node> node);
+
+ private:
+  std::vector<Ptr<Node> > m_nodes;
+};
+
+} // namespace ns3
+
+#endif /* NODE_CONTAINER_H */
--- a/src/node/node-list.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/node-list.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -22,7 +22,7 @@
 
 #include "ns3/composite-trace-resolver.h"
 #include "ns3/simulator.h"
-#include "ns3/simulation-singleton.h"
+#include "ns3/object-vector.h"
 #include "node-list.h"
 #include "node.h"
 
@@ -60,9 +60,10 @@
 /**
  * The private node list used by the static-based API
  */
-class NodeListPriv
+class NodeListPriv : public Object
 {
 public:
+  static TypeId GetTypeId (void);
   NodeListPriv ();
   ~NodeListPriv ();
 
@@ -73,10 +74,50 @@
   Ptr<Node> GetNode (uint32_t n);
   uint32_t GetNNodes (void);
 
+  static Ptr<NodeListPriv> Get (void);
+  
 private:
+  static Ptr<NodeListPriv> *DoGet (void);
+  static void Delete (void);
   std::vector<Ptr<Node> > m_nodes;
 };
 
+TypeId 
+NodeListPriv::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("NodeListPriv")
+    .SetParent<Object> ()
+    .AddAttribute ("NodeList", "The list of all nodes created during the simulation.",
+                   ObjectVector (),
+                   MakeObjectVectorAccessor (&NodeListPriv::m_nodes),
+                   MakeObjectVectorChecker ())
+    ;
+  return tid;
+}
+
+Ptr<NodeListPriv> 
+NodeListPriv::Get (void)
+{
+  return *DoGet ();
+}  
+Ptr<NodeListPriv> *
+NodeListPriv::DoGet (void)
+{
+  static Ptr<NodeListPriv> ptr = 0;
+  if (ptr == 0)
+    {
+      ptr = CreateObject<NodeListPriv> ();
+      Simulator::ScheduleDestroy (&NodeListPriv::Delete);
+    }
+  return &ptr;
+}
+void 
+NodeListPriv::Delete (void)
+{
+  (*DoGet ()) = 0;
+}
+
+
 NodeListPriv::NodeListPriv ()
 {}
 NodeListPriv::~NodeListPriv ()
@@ -143,42 +184,42 @@
 uint32_t
 NodeList::Add (Ptr<Node> node)
 {
-  return SimulationSingleton<NodeListPriv>::Get ()->Add (node);
+  return NodeListPriv::Get ()->Add (node);
 }
 NodeList::Iterator 
 NodeList::Begin (void)
 {
-  return SimulationSingleton<NodeListPriv>::Get ()->Begin ();
+  return NodeListPriv::Get ()->Begin ();
 }
 NodeList::Iterator 
 NodeList::End (void)
 {
-  return SimulationSingleton<NodeListPriv>::Get ()->End ();
+  return NodeListPriv::Get ()->End ();
 }
 Ptr<Node>
 NodeList::GetNode (uint32_t n)
 {
-  return SimulationSingleton<NodeListPriv>::Get ()->GetNode (n);
+  return NodeListPriv::Get ()->GetNode (n);
 }
 
 void 
 NodeList::Connect (std::string name, const CallbackBase &cb)
 {
-  SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->Connect (name, cb, TraceContext ());
+  NodeListPriv::Get ()->GetTraceResolver ()->Connect (name, cb, TraceContext ());
 }
 void 
 NodeList::Disconnect (std::string name, const CallbackBase &cb)
 {
-  SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->Disconnect (name, cb);
+  NodeListPriv::Get ()->GetTraceResolver ()->Disconnect (name, cb);
 }
 void 
 NodeList::TraceAll (std::ostream &os)
 {
-  SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ()->TraceAll (os, TraceContext ());
+  NodeListPriv::Get ()->GetTraceResolver ()->TraceAll (os, TraceContext ());
 }
 Ptr<TraceResolver> 
 NodeList::GetTraceResolver (void)
 {
-  return SimulationSingleton<NodeListPriv>::Get ()->GetTraceResolver ();
+  return NodeListPriv::Get ()->GetTraceResolver ();
 }
 }//namespace ns3
--- a/src/node/node.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/node.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -26,6 +26,8 @@
 #include "ns3/packet.h"
 #include "ns3/simulator.h"
 #include "ns3/composite-trace-resolver.h"
+#include "ns3/object-vector.h"
+#include "ns3/uinteger.h"
 
 namespace ns3{
 
@@ -35,68 +37,24 @@
 Node::GetTypeId (void)
 {
   static TypeId tid = TypeId ("Node")
-    .SetParent<Object> ();
+    .SetParent<Object> ()
+    .AddAttribute ("DeviceList", "The list of devices associated to this Node.",
+                   ObjectVector (),
+                   MakeObjectVectorAccessor (&Node::m_devices),
+                   MakeObjectVectorChecker ())
+    .AddAttribute ("ApplicationList", "The list of applications associated to this Node.",
+                   ObjectVector (),
+                   MakeObjectVectorAccessor (&Node::m_applications),
+                   MakeObjectVectorChecker ())
+    .AddAttribute ("Id", "The id (unique integer) of this Node.",
+                   TypeId::ATTR_GET, // allow only getting it.
+                   Uinteger (0),
+                   MakeUintegerAccessor (&Node::m_id),
+                   MakeUintegerChecker<uint32_t> ())
+    ;
   return tid;
 }
 
-NodeNetDeviceIndex::NodeNetDeviceIndex ()
-  : m_index (0)
-{}
-NodeNetDeviceIndex::NodeNetDeviceIndex (uint32_t index)
-  : m_index (index)
-{}
-uint32_t 
-NodeNetDeviceIndex::Get (void) const
-{
-  return m_index;
-}
-void 
-NodeNetDeviceIndex::Print (std::ostream &os) const
-{
-  os << "device=" << m_index;
-}
-uint16_t 
-NodeNetDeviceIndex::GetUid (void)
-{
-  static uint16_t uid = AllocateUid<NodeNetDeviceIndex> ("NodeNetDeviceIndex");
-  return uid;
-}
-std::string 
-NodeNetDeviceIndex::GetTypeName (void) const
-{
-  return "ns3::NodeNetDeviceIndex";
-}
-
-
-NodeApplicationIndex::NodeApplicationIndex ()
-  : m_index (0)
-{}
-NodeApplicationIndex::NodeApplicationIndex (uint32_t index)
-  : m_index (index)
-{}
-uint32_t 
-NodeApplicationIndex::Get (void) const
-{
-  return m_index;
-}
-void 
-NodeApplicationIndex::Print (std::ostream &os) const
-{
-  os << "device=" << m_index;
-}
-uint16_t 
-NodeApplicationIndex::GetUid (void)
-{
-  static uint16_t uid = AllocateUid<NodeApplicationIndex> ("NodeApplicationIndex");
-  return uid;
-}
-std::string 
-NodeApplicationIndex::GetTypeName (void) const
-{
-  return "ns3::NodeApplicationIndex";
-}
-
-
 Node::Node()
   : m_id(0), 
     m_sid(0)
@@ -122,16 +80,6 @@
 Node::~Node ()
 {}
 
-Ptr<TraceResolver>
-Node::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddArray ("devices", m_devices.begin (), m_devices.end (), NodeNetDeviceIndex ());
-  resolver->AddArray ("applications", m_applications.begin (), m_applications.end (), NodeApplicationIndex ());
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
-}
-
 uint32_t 
 Node::GetId (void) const
 {
--- a/src/node/node.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/node.h	Wed Feb 27 22:19:39 2008 +0100
@@ -25,56 +25,16 @@
 
 #include "ns3/object.h"
 #include "ns3/callback.h"
-#include "ns3/trace-context-element.h"
 #include "ns3/ptr.h"
 
 namespace ns3 {
 
 class TraceContext;
-class TraceResolver;
 class NetDevice;
 class Application;
 class Packet;
 class Address;
-class CompositeTraceResolver;
 
-/**
- * \brief hold in a TraceContext the index of a NetDevice within a Node
- */
-class NodeNetDeviceIndex : public TraceContextElement
-{
-public:
-  NodeNetDeviceIndex ();
-  NodeNetDeviceIndex (uint32_t index);
-  /**
-   * \returns the index of the NetDevice within its container Node.
-   */
-  uint32_t Get (void) const;
-  void Print (std::ostream &os) const;
-  std::string GetTypeName (void) const;
-  static uint16_t GetUid (void);
-private:
-  uint32_t m_index;
-};
-
-/**
- * \brief hold in a TraceContext the index of an Application within a Node
- */
-class NodeApplicationIndex : public TraceContextElement
-{
-public:
-  NodeApplicationIndex ();
-  NodeApplicationIndex (uint32_t index);
-  /**
-   * \returns the index of the Application within its container Node.
-   */
-  uint32_t Get (void) const;
-  void Print (std::ostream &os) const;
-  std::string GetTypeName (void) const;
-  static uint16_t GetUid (void);
-private:
-  uint32_t m_index;
-};
 
 /**
  * \brief A network Node.
@@ -199,7 +159,6 @@
   void UnregisterProtocolHandler (ProtocolHandler handler);
 
 protected:
-  virtual Ptr<TraceResolver> GetTraceResolver (void) const;
   /**
    * The dispose method. Subclasses must override this method
    * and must chain up to it by calling Node::DoDispose at the
--- a/src/node/wscript	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/node/wscript	Wed Feb 27 22:19:39 2008 +0100
@@ -28,6 +28,8 @@
         'tcp.cc',
         'ipv4.cc',
         'application.cc',
+        'node-container.cc',
+        'net-device-container.cc',
         ]
 
     headers = bld.create_obj('ns3header')
@@ -56,4 +58,6 @@
         'tcp.h',
         'ipv4.h',
         'application.h',
+        'node-container.h',
+        'net-device-container.h',
         ]
--- a/src/routing/olsr/olsr-agent-impl.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/routing/olsr/olsr-agent-impl.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -37,8 +37,9 @@
 #include "ns3/log.h"
 #include "ns3/random-variable.h"
 #include "ns3/inet-socket-address.h"
-#include "ns3/composite-trace-resolver.h"
-
+#include "ns3/boolean.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
 
 /********** Useful macros **********/
 
@@ -153,18 +154,45 @@
 TypeId 
 AgentImpl::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("OlsrAgentImpl")
+  static TypeId tid = TypeId ("olsr::AgentImpl")
     .SetParent<Agent> ()
-    .AddConstructor<AgentImpl,Ptr<Node> > ();
+    .AddConstructor<AgentImpl> ()
+    .AddAttribute ("HelloInterval", "XXX",
+                   OLSR_HELLO_INTERVAL,
+                   MakeTimeAccessor (&AgentImpl::m_helloInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("TcInterval", "XXX",
+                   OLSR_TC_INTERVAL,
+                   MakeTimeAccessor (&AgentImpl::m_tcInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("MidInterval", "XXX",
+                   OLSR_MID_INTERVAL,
+                   MakeTimeAccessor (&AgentImpl::m_midInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("Willingness", "XXX",
+                   Uinteger (OLSR_WILL_ALWAYS),
+                   MakeUintegerAccessor (&AgentImpl::m_willingness),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddTraceSource ("Rx", "Receive OLSR packet.",
+                     MakeTraceSourceAccessor (&AgentImpl::m_rxPacketTrace))
+    .AddTraceSource ("Tx", "Send OLSR packet.",
+                     MakeTraceSourceAccessor (&AgentImpl::m_txPacketTrace))
+    .AddTraceSource ("RoutingTableChanged", "The OLSR routing table has changed.",
+		     MakeTraceSourceAccessor (&AgentImpl::m_routingTableChanged))
+    ;
   return tid;
 }
 
 
-AgentImpl::AgentImpl (Ptr<Node> node)
+AgentImpl::AgentImpl ()
   :
   m_helloTimer (Timer::CANCEL_ON_DESTROY),
   m_tcTimer (Timer::CANCEL_ON_DESTROY),
   m_midTimer (Timer::CANCEL_ON_DESTROY)
+{}
+
+void
+AgentImpl::SetNode (Ptr<Node> node)
 {
   NS_LOG_DEBUG ("Created olsr::AgentImpl");
   m_helloTimer.SetFunction (&AgentImpl::HelloTimerExpire, this);
@@ -172,18 +200,10 @@
   m_midTimer.SetFunction (&AgentImpl::MidTimerExpire, this);
   m_queuedMessagesTimer.SetFunction (&AgentImpl::SendQueuedMessages, this);
 
-  // Aggregate with the Node, so that OLSR dies when the node is destroyed.
-  node->AggregateObject (this);
-
   m_packetSequenceNumber = OLSR_MAX_SEQ_NUM;
   m_messageSequenceNumber = OLSR_MAX_SEQ_NUM;
   m_ansn = OLSR_MAX_SEQ_NUM;
 
-  m_helloInterval = OLSR_HELLO_INTERVAL;
-  m_tcInterval = OLSR_TC_INTERVAL;
-  m_midInterval = OLSR_MID_INTERVAL;
-  m_willingness = OLSR_WILL_ALWAYS;
-
   m_linkTupleTimerFirstTime = true;
 
   m_ipv4 = node->GetObject<Ipv4> ();
@@ -280,32 +300,6 @@
 }
 
 
-Ptr<TraceResolver> 
-AgentImpl::GetTraceResolver (void) const
-{
-  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
-  resolver->AddSource ("rx",
-                       TraceDoc ("receive OLSR packet",
-                                 "const olsr::PacketHeader &", "header of OLSR packet received",
-                                 "const olsr::MessageList &", "list of OLSR messages contained in the packet"
-                                 ),
-                       m_rxPacketTrace);
-  resolver->AddSource ("tx",
-                       TraceDoc ("send OLSR packet",
-                                 "const olsr::PacketHeader &", "header of OLSR packet sent",
-                                 "const olsr::MessageList &", "list of OLSR messages contained in the packet"
-                                 ),
-                       m_txPacketTrace);
-  resolver->AddSource ("RoutingTableChanged",
-                       TraceDoc ("the OLSR routing table has changed",
-                                 "uint32_t", "size of the new routing table"
-                                 ),
-                       m_routingTableChanged);
-  resolver->SetParentResolver (Object::GetTraceResolver ());
-  return resolver;
-}
-
-
 //
 // \brief Processes an incoming %OLSR packet following RFC 3626 specification.
 void
--- a/src/routing/olsr/olsr-agent-impl.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/routing/olsr/olsr-agent-impl.h	Wed Feb 27 22:19:39 2008 +0100
@@ -39,7 +39,7 @@
 #include "ns3/socket.h"
 #include "ns3/event-garbage-collector.h"
 #include "ns3/timer.h"
-#include "ns3/callback-trace-source.h"
+#include "ns3/traced-callback.h"
 
 
 namespace ns3 {
@@ -51,7 +51,9 @@
 public:
   static TypeId GetTypeId (void);
 
-  AgentImpl (Ptr<Node> node);
+  AgentImpl ();
+
+  virtual void SetNode (Ptr<Node> node);
 
   virtual void Start ();
   virtual void SetMainInterface (uint32_t interface);
@@ -87,7 +89,6 @@
 	
 protected:
   void DoDispose ();
-  Ptr<TraceResolver> GetTraceResolver (void) const;
 
   void SendPacket (Ptr<Packet> packet, const MessageList &containedMessages);
 	
@@ -183,11 +184,11 @@
   // HELLO messages arrive)
   std::map< Ptr<Socket>, Ipv4Address > m_socketAddresses;
 
-  CallbackTraceSource <const PacketHeader &,
-                       const MessageList &> m_rxPacketTrace;
-  CallbackTraceSource <const PacketHeader &,
-                       const MessageList &> m_txPacketTrace;
-  CallbackTraceSource <uint32_t> m_routingTableChanged;
+  TracedCallback <const PacketHeader &,
+                  const MessageList &> m_rxPacketTrace;
+  TracedCallback <const PacketHeader &,
+                  const MessageList &> m_txPacketTrace;
+  TracedCallback <uint32_t> m_routingTableChanged;
 
 };
 
--- a/src/routing/olsr/olsr-agent.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/routing/olsr/olsr-agent.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -19,17 +19,10 @@
  */
 
 #include "olsr-agent.h"
-#include "ns3/type-id-default-value.h"
 
 namespace ns3 {
 namespace olsr {
 
-static TypeIdDefaultValue g_defaultImpl =
-  TypeIdDefaultValue ("OlsrAgentType",
-                           "The type of OlsrAgent implementation",
-                           Agent::GetTypeId (),
-                           "OlsrAgentImpl");
-
 NS_OBJECT_ENSURE_REGISTERED (Agent);
 
 TypeId 
@@ -40,13 +33,4 @@
   return tid;
 }
 
-Ptr<Agent> 
-Agent::CreateDefault (Ptr<Node> node)
-{
-  TypeId tid = g_defaultImpl.GetValue ();
-  Ptr<Agent> agent = tid.CreateObject (node)->GetObject<Agent> ();
-  return agent;
-}
-
-
 }}
--- a/src/routing/olsr/olsr-agent.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/routing/olsr/olsr-agent.h	Wed Feb 27 22:19:39 2008 +0100
@@ -47,7 +47,7 @@
 public:
   static TypeId GetTypeId (void);
 
-  static Ptr<Agent> CreateDefault (Ptr<Node> node);
+  virtual void SetNode (Ptr<Node> node) = 0;
 
   /**
    * \brief Sets the main interface to be used by OLSR
@@ -74,7 +74,6 @@
   virtual void Start () = 0;
 };
 
-
 }} // namespace olsr, ns3
 
 #endif /* OLSR_AGENT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-helper.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,52 @@
+#include "olsr-helper.h"
+#include "olsr-agent.h"
+#include "ns3/node-list.h"
+
+namespace ns3 {
+
+OlsrHelper::OlsrHelper ()
+{
+  m_agentFactory.SetTypeId ("olsr::AgentImpl");
+}
+
+void 
+OlsrHelper::SetAgent (std::string tid,
+		      std::string n0, Attribute v0,
+		      std::string n1, Attribute v1,
+		      std::string n2, Attribute v2,
+		      std::string n3, Attribute v3,
+		      std::string n4, Attribute v4,
+		      std::string n5, Attribute v5,
+		      std::string n6, Attribute v6,
+		      std::string n7, Attribute v7)
+{
+  m_agentFactory.SetTypeId (tid);
+  m_agentFactory.Set (n0, v0);
+  m_agentFactory.Set (n1, v1);
+  m_agentFactory.Set (n2, v2);
+  m_agentFactory.Set (n3, v3);
+  m_agentFactory.Set (n4, v4);
+  m_agentFactory.Set (n5, v5);
+  m_agentFactory.Set (n6, v6);
+  m_agentFactory.Set (n7, v7);
+}
+
+void 
+OlsrHelper::Enable (NodeContainer container)
+{
+  Enable (container.Begin (), container.End ());
+}
+void 
+OlsrHelper::Enable (Ptr<Node> node)
+{
+  Ptr<olsr::Agent> agent = m_agentFactory.Create<olsr::Agent> ();
+  agent->SetNode (node);
+  node->AggregateObject (agent);
+}
+void 
+OlsrHelper::EnableAll (void)
+{
+  Enable (NodeList::Begin (), NodeList::End ());
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/olsr/olsr-helper.h	Wed Feb 27 22:19:39 2008 +0100
@@ -0,0 +1,52 @@
+#ifndef OLSR_HELPER_H
+#define OLSR_HELPER_H
+
+#include "ns3/object-factory.h"
+#include "ns3/node-container.h"
+#include "ns3/node.h"
+
+namespace ns3 {
+
+class OlsrHelper
+{
+public:
+  OlsrHelper ();
+
+  void SetAgent (std::string tid,
+		 std::string n0 = "", Attribute v0 = Attribute (),
+		 std::string n1 = "", Attribute v2 = Attribute (),
+		 std::string n2 = "", Attribute v2 = Attribute (),
+		 std::string n3 = "", Attribute v3 = Attribute (),
+		 std::string n4 = "", Attribute v4 = Attribute (),
+		 std::string n5 = "", Attribute v5 = Attribute (),
+		 std::string n6 = "", Attribute v6 = Attribute (),
+		 std::string n7 = "", Attribute v7 = Attribute ());
+
+  template <typename InputIterator>
+  void Enable (InputIterator begin, InputIterator end);
+  void Enable (NodeContainer container);
+  void Enable (Ptr<Node> node);
+  void EnableAll (void);
+private:
+  ObjectFactory m_agentFactory;
+};
+
+} // namespace ns3
+
+namespace ns3 {
+
+template <typename T>
+void 
+OlsrHelper::Enable (T begin, T end)
+{
+  for (T i = begin; i != end; i++)
+    {
+      Ptr<Object> obj = (*i);
+      Ptr<Node> node = obj->GetObject<Node> ();
+      Enable (node);
+    }
+}
+
+} // namespace ns3
+
+#endif /* OLSR_HELPER_H */
--- a/src/routing/olsr/wscript	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/routing/olsr/wscript	Wed Feb 27 22:19:39 2008 +0100
@@ -9,13 +9,13 @@
         'routing-table.cc',
         'olsr-agent.cc',
         'olsr-agent-impl.cc',
-        'olsr.cc',
+        'olsr-helper.cc',
         ]
 
     headers = bld.create_obj('ns3header')
     headers.source = [
         'olsr-agent.h',
-        'olsr.h',
         'olsr-header.h',
+        'olsr-helper.h',
         ]
 
--- a/src/simulator/event-impl.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/simulator/event-impl.h	Wed Feb 27 22:19:39 2008 +0100
@@ -21,10 +21,12 @@
 #define EVENT_IMPL_H
 
 #include <stdint.h>
+#include "ns3/object-base.h"
 
 namespace ns3 {
 
-class EventImpl {
+class EventImpl : public ObjectBase 
+{
 public:
   EventImpl ();
   inline void Ref (void) const;
--- a/src/simulator/nstime.h	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/simulator/nstime.h	Wed Feb 27 22:19:39 2008 +0100
@@ -20,9 +20,11 @@
 #ifndef TIME_H
 #define TIME_H
 
+#include "ns3/assert.h"
+#include "ns3/attribute.h"
+#include "ns3/attribute-helper.h"
 #include <stdint.h>
 #include <math.h>
-#include "ns3/assert.h"
 #include <ostream>
 #include "high-precision.h"
 #include "cairo-wideint-private.h"
@@ -334,6 +336,8 @@
 // additional methods that should not be available for N!=1
 // \class TimeUnit<1>
 
+class TimeValue;
+
 template <>
 class TimeUnit<1>
 {
@@ -431,6 +435,9 @@
 
   static uint64_t UnitsToTimestep (uint64_t unitValue, 
                                    uint64_t unitFactor);
+
+  TimeUnit (Attribute value);
+  operator Attribute () const;
 private:
   HighPrecision m_data;
 
@@ -513,7 +520,8 @@
 typedef TimeUnit<1> Time;
 
 
-std::ostream& operator<< (std::ostream& os, Time const& time);
+std::ostream& operator<< (std::ostream& os, const Time & time);
+std::istream& operator>> (std::istream& is, Time & time);
 
 /**
  * \brief create ns3::Time instances in units of seconds.
@@ -661,7 +669,10 @@
 typedef TimeUnit<-1> TimeInvert;
 typedef TimeUnit<2> TimeSquare;
 
+ATTRIBUTE_ACCESSOR_DEFINE (Time);
+ATTRIBUTE_VALUE_DEFINE (Time);
+ATTRIBUTE_CHECKER_DEFINE (Time);
 
-}; // namespace ns3
+} // namespace ns3
 
 #endif /* TIME_H */
--- a/src/simulator/simulator.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/simulator/simulator.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -572,7 +572,7 @@
 {}
   
 
-class SimulatorTests : public Test {
+class SimulatorTests : public Test, public ObjectBase {
 public:
   SimulatorTests ();
   // only here for testing of Ptr<>
--- a/src/simulator/time.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/src/simulator/time.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -22,6 +22,7 @@
 #include "nstime.h"
 #include "ns3/fatal-error.h"
 #include "ns3/default-value.h"
+#include "ns3/object.h"
 #include <math.h>
 
 namespace ns3 {
@@ -188,7 +189,7 @@
 
 
 std::ostream& 
-operator<< (std::ostream& os, Time const& time)
+operator<< (std::ostream& os, const Time & time)
 {
   std::string unit;
   switch (TimeStepPrecision::Get ()) {
@@ -214,6 +215,60 @@
   os << time.GetTimeStep () << unit;
   return os;
 }
+std::istream& operator>> (std::istream& is, Time & time)
+{
+  std::string value;
+  is >> value;
+  std::string::size_type n = value.find_first_not_of("0123456789.");
+  if (n == std::string::npos)
+    {
+      is.setstate (std::ios_base::failbit);
+      return is;
+    }
+  std::string trailer = value.substr(n, value.size ()-1-n);
+  std::istringstream iss;
+  iss.str (value.substr(0, n));
+
+  if (trailer == std::string("s"))
+    {
+      double v;
+      iss >> v;
+      time = Seconds (v);
+      return is;
+    }
+  uint64_t integer;
+  iss >> integer;
+  if (is.bad () || is.fail ())
+    {
+      is.setstate (std::ios_base::failbit);
+    }
+  else if (trailer == std::string("ms"))
+    {
+      time = MilliSeconds (integer);
+    }
+  else if (trailer == std::string("us"))
+    {
+      time = MicroSeconds (integer);
+    }
+  else if (trailer == std::string("ns"))
+    {
+      time = NanoSeconds (integer);
+    }
+  else if (trailer == std::string("ps"))
+    {
+      time = PicoSeconds (integer);
+    }
+  else if (trailer == std::string("fs"))
+    {
+      time = FemtoSeconds (integer);
+    }
+  else
+    {
+      is.setstate (std::ios_base::failbit);
+      // XXX: problem ?
+    }
+  return is;
+}
 
 Time Seconds (double seconds)
 {
@@ -241,6 +296,23 @@
   return unitValue;
 }
 
+TimeUnit<1>::TimeUnit (Attribute value)
+{
+  const TimeValue *v = value.DynCast<const TimeValue *> ();
+  if (v == 0)
+    {
+      NS_FATAL_ERROR ("Unexpected type of value. Expected \"TimeValue\"");
+    }
+  *this = v->Get ();
+}
+TimeUnit<1>::operator Attribute () const
+{
+  return Attribute::Create<TimeValue> (*this);
+}
+
+ATTRIBUTE_VALUE_IMPLEMENT (Time);
+ATTRIBUTE_CHECKER_IMPLEMENT (Time);
+
 Time MilliSeconds (uint64_t ms)
 {
   uint64_t ts = TimeUnit<1>::UnitsToTimestep(ms, TimeStepPrecision::MS_FACTOR);
@@ -268,6 +340,8 @@
   uint64_t ts = TimeUnit<1>::UnitsToTimestep(fs, TimeStepPrecision::FS_FACTOR);
   return TimeStep(ts);
 }
+
+
 /*
  * The timestep value passed to this function must be of the precision
  * of TimeStepPrecision::Get
@@ -287,7 +361,7 @@
   return GetHighPrecision ().GetDouble ();
 }
 
-}; // namespace ns3
+} // namespace ns3
 
 
 #ifdef RUN_SELF_TESTS
--- a/tutorial/point-to-point-ipv4-topology.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/point-to-point-ipv4-topology.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -43,8 +43,10 @@
 {
   NS_ASSERT (channel->GetNDevices () <= 1);
 
-  Ptr<PointToPointNetDevice> nd = CreateObject<PointToPointNetDevice> (node);
-
+  Ptr<PointToPointNetDevice> nd = 
+    CreateObjectWith<PointToPointNetDevice> ("Node", node, 
+                                             "Address", Mac48Address::Allocate ());
+  node->AddDevice (nd);
   Ptr<Queue> q = Queue::CreateDefault ();
   nd->AddQueue(q);
   nd->Attach (channel);
--- a/tutorial/tutorial-bus-network.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-bus-network.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -21,6 +21,8 @@
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
 #include "ns3/ascii-trace.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 #include "ipv4-bus-network.h"
 
@@ -41,11 +43,19 @@
   uint32_t port = 7;
 
   Ptr<Node> n0 = bus.GetNode (0);
-  Ptr<UdpEchoClient> client =  CreateObject<UdpEchoClient> (n0, "10.1.0.1", 
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client =  
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+				     "RemoteIpv4", Ipv4Address ("10.1.0.1"),
+				     "RemotePort", Uinteger (port),
+				     "MaxPackets", Uinteger (1), 
+				     "Interval", Seconds(1.), 
+				     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
   Ptr<Node> n1 = bus.GetNode (1);
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-csma-echo-ascii-trace.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-csma-echo-ascii-trace.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -27,6 +27,8 @@
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
 #include "ns3/ascii-trace.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 NS_LOG_COMPONENT_DEFINE ("UdpEchoSimulation");
 
@@ -66,10 +68,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", 
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-csma-echo-pcap-trace.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-csma-echo-pcap-trace.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -28,6 +28,8 @@
 #include "ns3/nstime.h"
 #include "ns3/ascii-trace.h"
 #include "ns3/pcap-trace.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 NS_LOG_COMPONENT_DEFINE ("UdpEchoSimulation");
 
@@ -67,10 +69,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-csma-echo.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-csma-echo.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -26,6 +26,8 @@
 #include "ns3/udp-echo-server.h"
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
+#include "ns3/uinteger.h"
+#include "ns3/inet-socket-address.h"
 
 NS_LOG_COMPONENT_DEFINE ("UdpEchoSimulation");
 
@@ -65,10 +67,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2",
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-linear-dumbbell.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-linear-dumbbell.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -32,6 +32,8 @@
 #include "ns3/ascii-trace.h"
 #include "ns3/pcap-trace.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 NS_LOG_COMPONENT_DEFINE ("DumbbellSimulation");
 
@@ -124,19 +126,55 @@
 //
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client0 = CreateObject<UdpEchoClient> (n0, "10.1.2.1", 
-    port, 100, Seconds(.01), 1024);
-  Ptr<UdpEchoClient> client1 = CreateObject<UdpEchoClient> (n1, "10.1.2.2", 
-    port, 100, Seconds(.01), 1024);
-  Ptr<UdpEchoClient> client2 = CreateObject<UdpEchoClient> (n2, "10.1.2.3", 
-    port, 100, Seconds(.01), 1024);
-  Ptr<UdpEchoClient> client3 = CreateObject<UdpEchoClient> (n3, "10.1.2.4", 
-    port, 100, Seconds(.01), 1024);
+  Ptr<UdpEchoClient> client0 = 
+    CreateObjectWith<UdpEchoClient> (
+                                     "Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.2.1"),
+                                     "RemotePort", Uinteger (port),
+                                     "MaxPackets", Uinteger (100),
+                                     "Interval", Seconds (0.01),
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client0);
+  Ptr<UdpEchoClient> client1 = 
+    CreateObjectWith<UdpEchoClient> (
+                                     "Node", n1, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.2.2"),
+                                     "RemotePort", Uinteger (port),
+                                     "MaxPackets", Uinteger (100),
+                                     "Interval", Seconds (0.01),
+                                     "PacketSize", Uinteger (1024));
+  n1->AddApplication (client1);
+  Ptr<UdpEchoClient> client2 = 
+    CreateObjectWith<UdpEchoClient> (
+                                     "Node", n2, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.2.3"),
+                                     "RemotePort", Uinteger (port),
+                                     "MaxPackets", Uinteger (100),
+                                     "Interval", Seconds (0.01),
+                                     "PacketSize", Uinteger (1024));
+  n2->AddApplication (client2);
+  Ptr<UdpEchoClient> client3 = 
+    CreateObjectWith<UdpEchoClient> (
+                                     "Node", n3, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.2.4"),
+                                     "RemotePort", Uinteger (port),
+                                     "MaxPackets", Uinteger (100),
+                                     "Interval", Seconds (0.01),
+                                     "PacketSize", Uinteger (1024));
+  n3->AddApplication (client3);
 
-  Ptr<UdpEchoServer> server4 = CreateObject<UdpEchoServer> (n4, port);
-  Ptr<UdpEchoServer> server5 = CreateObject<UdpEchoServer> (n5, port);
-  Ptr<UdpEchoServer> server6 = CreateObject<UdpEchoServer> (n6, port);
-  Ptr<UdpEchoServer> server7 = CreateObject<UdpEchoServer> (n7, port);
+  Ptr<UdpEchoServer> server4 = 
+    CreateObjectWith<UdpEchoServer> ("Node", n4, "Port", Uinteger (port));
+  n4->AddApplication (server4);
+  Ptr<UdpEchoServer> server5 = 
+    CreateObjectWith<UdpEchoServer> ("Node", n5, "Port", Uinteger (port));
+  n5->AddApplication (server5);
+  Ptr<UdpEchoServer> server6 = 
+    CreateObjectWith<UdpEchoServer> ("Node", n6, "Port", Uinteger (port));
+  n6->AddApplication (server6);
+  Ptr<UdpEchoServer> server7 = 
+    CreateObjectWith<UdpEchoServer> ("Node", n7, "Port", Uinteger (port));
+  n7->AddApplication (server7);
 
   server4->Start(Seconds(1.));
   server5->Start(Seconds(1.));
--- a/tutorial/tutorial-point-to-point.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-point-to-point.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -28,6 +28,8 @@
 #include "ns3/ascii-trace.h"
 #include "ns3/pcap-trace.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 NS_LOG_COMPONENT_DEFINE ("PointToPointSimulation");
 
@@ -58,10 +60,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", 
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"), 
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-star-routing.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-star-routing.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -27,6 +27,8 @@
 #include "ns3/ascii-trace.h"
 #include "ns3/pcap-trace.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 #include "point-to-point-ipv4-topology.h"
 
@@ -145,10 +147,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n4, "10.1.1.2", 
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n4, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/tutorial/tutorial-star.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/tutorial/tutorial-star.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -27,6 +27,8 @@
 #include "ns3/ascii-trace.h"
 #include "ns3/pcap-trace.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/uinteger.h"
 
 #include "point-to-point-ipv4-topology.h"
 
@@ -145,10 +147,19 @@
 
   uint16_t port = 7;
 
-  Ptr<UdpEchoClient> client = CreateObject<UdpEchoClient> (n0, "10.1.1.2", 
-    port, 1, Seconds(1.), 1024);
+  Ptr<UdpEchoClient> client = 
+    CreateObjectWith<UdpEchoClient> ("Node", n0, 
+                                     "RemoteIpv4", Ipv4Address ("10.1.1.2"),
+                                     "RemotePort", Uinteger (port), 
+                                     "MaxPackets", Uinteger (1), 
+                                     "Interval", Seconds(1.), 
+                                     "PacketSize", Uinteger (1024));
+  n0->AddApplication (client);
 
-  Ptr<UdpEchoServer> server = CreateObject<UdpEchoServer> (n1, port);
+  Ptr<UdpEchoServer> server = 
+    CreateObjectWith<UdpEchoServer> ("Node", n1, 
+                                     "Port", Uinteger (port));
+  n1->AddApplication (server);
 
   server->Start(Seconds(1.));
   client->Start(Seconds(2.));
--- a/utils/mobility-visualizer-model.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/utils/mobility-visualizer-model.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -5,7 +5,7 @@
 #include "ns3/ptr.h"
 #include "ns3/mobility-model.h"
 #include "ns3/mobility-model-notifier.h"
-#include "ns3/random-topology.h"
+#include "ns3/position-allocator.h"
 #include "ns3/default-value.h"
 #include "ns3/command-line.h"
 #include "ns3/command-line.h"
@@ -15,6 +15,7 @@
 #include "ns3/node-list.h"
 #include "ns3/rectangle-default-value.h"
 #include "ns3/type-id-default-value.h"
+#include "ns3/mobility-helper.h"
 
 #include "mobility-visualizer.h"
 
@@ -89,20 +90,21 @@
 
   CommandLine::Parse (argc, argv);
 
-  RandomTopology topology;
+  MobilityHelper mobility;
 
   for (uint32_t i = 0; i < g_numNodes; i++)
     {
       Ptr<Node> node = CreateObject<Node> ();
-      node->AggregateObject (CreateObject<MobilityModelNotifier> ());
     }
 
-  topology.Layout (NodeList::Begin (), NodeList::End ());
+  mobility.EnableNotifier ();
+  mobility.Layout (NodeList::Begin (), NodeList::End ());
 
   Simulator::Schedule (g_sampleInterval, Sample);
 
-  TypeId mobType = DefaultValueListGet<TypeIdDefaultValue> ("RandomTopologyMobilityType")->GetValue ();
-  if (mobType.GetName () == "RandomWalkMobilityModel")
+  // XXX: The following is not really going to work with the params.
+
+  if (mobility.GetMobilityModelType () == "RandomWalk2dMobilityModel")
     {
       Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomWalk2dBounds")->GetValue ();
       *x1 = bounds.xMin;
@@ -112,7 +114,7 @@
       std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
                 << bounds.yMin << " " << bounds.yMax << std::endl;
     }
-  else if (mobType.GetName () == "RandomDirection2dMobilityModel")
+  else if (mobility.GetMobilityModelType () == "RandomDirection2dMobilityModel")
     {
       Rectangle bounds = DefaultValueListGet<RectangleDefaultValue> ("RandomDirection2dArea")->GetValue ();
       *x1 = bounds.xMin;
@@ -122,7 +124,7 @@
       std::cout << "RECT " << bounds.xMin << " " << bounds.xMax << " "
                 << bounds.yMin << " " << bounds.yMax << std::endl;      
     }
-  else if (mobType.GetName () == "RandomWaypointMobilityModel")
+  else if (mobility.GetMobilityModelType () == "RandomWaypointMobilityModel")
     {
       std::cerr << "bounds for RandomWaypointMobilityModel not implemented" << std::endl;
       //ClassId posType = DefaultValueList::Get<ClassIdDefaultValue> ("RandomWaypointPosition")->GetValue ();
@@ -130,7 +132,7 @@
     }
   else
     {
-      NS_FATAL_ERROR ("mobility type " << mobType.GetName () << " not supported");
+      NS_FATAL_ERROR ("mobility type " << mobility.GetMobilityModelType () << " not supported");
     }
 
   std::cerr << g_sampleInterval << std::endl;
--- a/utils/print-introspected-doxygen.cc	Tue Feb 26 01:39:59 2008 +0100
+++ b/utils/print-introspected-doxygen.cc	Wed Feb 27 22:19:39 2008 +0100
@@ -7,6 +7,7 @@
 #include "ns3/queue.h"
 #include "ns3/mobility-model-notifier.h"
 #include "ns3/default-value.h"
+#include "ns3/string.h"
 
 using namespace ns3;
 
@@ -119,9 +120,14 @@
   Ptr<Node> node = CreateObject<InternetNode> ();
   node->AggregateObject (CreateObject<MobilityModelNotifier> ());
 
-  Ptr<PointToPointNetDevice> p2p = CreateObject<PointToPointNetDevice> (node);
+  Ptr<PointToPointNetDevice> p2p = CreateObjectWith<PointToPointNetDevice> ("Node", node, 
+									    "Address", Mac48Address::Allocate ());
+  node->AddDevice (p2p);
   p2p->AddQueue (Queue::CreateDefault ());
-  Ptr<CsmaNetDevice> csma = CreateObject<CsmaNetDevice> (node);
+  Ptr<CsmaNetDevice> csma = CreateObjectWith<CsmaNetDevice> ("Node", node, 
+							     "Address", Mac48Address::Allocate (),
+							     "EncapsulationMode", String ("Llc"));
+  node->AddDevice (csma);
   csma->AddQueue (Queue::CreateDefault ());
 
   TraceResolver::SourceCollection collection;