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;