Rename file names from serial to p2p
authorTom Henderson <tomh@tomh.org>
Sun, 25 Mar 2007 06:59:11 -0700
changeset 368 1df1165d6a68
parent 367 be64c89ac945
child 369 29ea5d1a83c8
Rename file names from serial to p2p
SConstruct
examples/simple-p2p.cc
examples/simple-serial.cc
samples/main-p2p-net-device-if.cc
samples/main-serial-net-device-if.cc
src/devices/p2p-gfr/p2p-channel.cc
src/devices/p2p-gfr/p2p-channel.h
src/devices/p2p-gfr/p2p-net-device.cc
src/devices/p2p-gfr/p2p-net-device.h
src/devices/p2p/layer-connector.cc
src/devices/p2p/layer-connector.h
src/devices/p2p/p2p-channel.cc
src/devices/p2p/p2p-channel.h
src/devices/p2p/p2p-net-device.cc
src/devices/p2p/p2p-net-device.h
src/devices/p2p/p2p-phy.cc
src/devices/p2p/p2p-phy.h
src/devices/p2p/p2p-topology.cc
src/devices/p2p/p2p-topology.h
src/devices/p2p/propagator.h
src/devices/serial/layer-connector.cc
src/devices/serial/layer-connector.h
src/devices/serial/propagator.h
src/devices/serial/serial-channel.cc
src/devices/serial/serial-channel.h
src/devices/serial/serial-net-device.cc
src/devices/serial/serial-net-device.h
src/devices/serial/serial-phy.cc
src/devices/serial/serial-phy.h
src/devices/serial/serial-topology.cc
src/devices/serial/serial-topology.h
--- a/SConstruct	Sun Mar 25 06:43:34 2007 -0700
+++ b/SConstruct	Sun Mar 25 06:59:11 2007 -0700
@@ -274,24 +274,24 @@
     'p2p-channel.h',
     ])
 
-serial = build.Ns3Module ('serial', 'src/devices/serial')
-ns3.add (serial)
-serial.add_deps (['node'])
-serial.add_sources ([
-    'serial-net-device.cc',
-    'serial-channel.cc',
-    'serial-topology.cc',
-    'serial-phy.cc',
+p2p = build.Ns3Module ('p2p', 'src/devices/p2p')
+ns3.add (p2p)
+p2p.add_deps (['node'])
+p2p.add_sources ([
+    'p2p-net-device.cc',
+    'p2p-channel.cc',
+    'p2p-topology.cc',
+    'p2p-phy.cc',
     'layer-connector.cc',
     ])
-serial.add_headers ([
+p2p.add_headers ([
     'propagator.h',
     ])
-serial.add_inst_headers ([
-    'serial-net-device.h',
-    'serial-channel.h',
-    'serial-topology.h',
-    'serial-phy.h',
+p2p.add_inst_headers ([
+    'p2p-net-device.h',
+    'p2p-channel.h',
+    'p2p-topology.h',
+    'p2p-phy.h',
     'layer-connector.h',
     ])
 
@@ -366,11 +366,11 @@
 sample_test.add_dep('core')
 sample_test.add_source('main-test.cc')
 
-sample_serial_net_device_if = build.Ns3Module ('sample-serial-net-device-if', 'samples')
-sample_serial_net_device_if.set_executable ()
-ns3.add (sample_serial_net_device_if)
-sample_serial_net_device_if.add_deps (['common', 'node', 'serial'])
-sample_serial_net_device_if.add_source ('main-serial-net-device-if.cc')
+sample_p2p_net_device_if = build.Ns3Module ('sample-p2p-net-device-if', 'samples')
+sample_p2p_net_device_if.set_executable ()
+ns3.add (sample_p2p_net_device_if)
+sample_p2p_net_device_if.add_deps (['common', 'node', 'p2p'])
+sample_p2p_net_device_if.add_source ('main-p2p-net-device-if.cc')
 
 sample_simple = build.Ns3Module('sample-simple', 'samples')
 sample_simple.set_executable()
@@ -385,10 +385,10 @@
 sample_sp2p.add_source('main-simple-p2p.cc')
 
 # examples
-example_simple_serial = build.Ns3Module('simple-serial', 'examples')
-example_simple_serial.set_executable()
-ns3.add(example_simple_serial)
-example_simple_serial.add_deps(['core', 'simulator', 'node', 'serial'])
-example_simple_serial.add_source('simple-serial.cc')
+example_simple_p2p = build.Ns3Module('simple-p2p', 'examples')
+example_simple_p2p.set_executable()
+ns3.add(example_simple_p2p)
+example_simple_p2p.add_deps(['core', 'simulator', 'node', 'p2p'])
+example_simple_p2p.add_source('simple-p2p.cc')
 
 ns3.generate_dependencies()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/simple-p2p.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,297 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * ns-2 simple.tcl script (ported from ns-2)
+ * Originally authored by Steve McCanne, 12/19/1996
+ */
+
+// Port of ns-2/tcl/ex/simple.tcl to ns-3
+//
+// Network topology
+//
+//  n0
+//     \ 5 Mb/s, 2ms
+//      \          1.5Mb/s, 10ms
+//       n2 -------------------------n3
+//      /
+//     / 5 Mb/s, 2ms
+//   n1
+//
+// - all links are p2p links with indicated one-way BW/delay
+// - CBR/UDP flows from n0 to n3, and from n3 to n1
+// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
+// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
+// - DropTail queues 
+// - Tracing of queues and packet receptions to file "out.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/debug.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/trace-writer.h"
+
+#include "ns3/internet-node.h"
+#include "ns3/p2p-channel.h"
+#include "ns3/p2p-net-device.h"
+#include "ns3/mac-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/arp-ipv4-interface.h"
+#include "ns3/ipv4.h"
+#include "ns3/datagram-socket.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/drop-tail.h"
+#include "ns3/trace-writer.h"
+#include "ns3/llc-snap-header.h"
+#include "ns3/arp-header.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/udp-header.h"
+#include "ns3/node-list.h"
+#include "ns3/trace-root.h"
+#include "ns3/object-container.h"
+#include "ns3/p2p-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/random-variable.h"
+
+using namespace ns3;
+
+class AsciiTrace 
+{
+public:
+  AsciiTrace (std::string filename);
+  ~AsciiTrace ();
+  void TraceAllQueues (void);
+  void TraceAllNetDeviceRx (void);
+private:
+  void LogDevQueue (TraceContext const &context, const Packet &p);
+  void LogDevRx (TraceContext const &context, Packet &p);
+  std::ofstream m_os;
+};
+
+AsciiTrace::AsciiTrace (std::string filename)
+{
+  m_os.open (filename.c_str ());
+}
+AsciiTrace::~AsciiTrace ()
+{
+  m_os.close ();
+}
+void
+AsciiTrace::TraceAllQueues (void)
+{
+  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
+                      MakeCallback (&AsciiTrace::LogDevQueue, this));
+}
+void
+AsciiTrace::TraceAllNetDeviceRx (void)
+{
+  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/rx",
+                      MakeCallback (&AsciiTrace::LogDevRx, this));
+}
+
+void 
+AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &p)
+{
+  enum Queue::TraceType type;
+  context.Get (type);
+  switch (type) 
+    {
+    case Queue::ENQUEUE:
+      m_os << "+ ";
+      break;
+    case Queue::DEQUEUE:
+      m_os << "- ";
+      break;
+    case Queue::DROP:
+      m_os << "d ";
+      break;
+    }
+  m_os << Simulator::Now ().GetSeconds () << " ";
+  NodeList::NodeIndex nodeIndex;
+  context.Get (nodeIndex);
+  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+  Ipv4::InterfaceIndex interfaceIndex;
+  context.Get (interfaceIndex);
+  m_os << "interface=" << interfaceIndex << " ";
+  m_os << "pkt-uid=" << p.GetUid () << " ";
+  m_os << std::endl;
+}
+void 
+AsciiTrace::LogDevRx (TraceContext const &context, Packet &p)
+{
+  m_os << "r " << Simulator::Now ().GetSeconds () << " ";
+  NodeList::NodeIndex nodeIndex;
+  context.Get (nodeIndex);
+  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+  Ipv4::InterfaceIndex interfaceIndex;
+  context.Get (interfaceIndex);
+  m_os << "interface=" << interfaceIndex << " ";
+  m_os << "pkt-uid=" << p.GetUid () << " ";
+  m_os << std::endl;  
+}
+
+
+static void
+GenerateTraffic (DatagramSocket *socket, uint32_t size)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " tx bytes=" << size << std::endl;
+  socket->SendDummy (size);
+  if (size > 50)
+    {
+      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
+    }
+}
+
+static void
+DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " rx bytes=" << size << std::endl;
+}
+
+static void
+PrintTraffic (DatagramSocket *socket)
+{
+  socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
+}
+
+#if 0
+static void
+PrintRoutingTable (InternetNode *a, std::string name)
+{
+  Ipv4 *ipv4 = a->GetIpv4 ();
+  std::cout << "interfaces node="<<name<<std::endl;
+  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
+    {
+      Ipv4Interface *interface = ipv4->GetInterface (i);
+      std::cout << "interface addr="<<interface->GetAddress () 
+                << ", netmask="<<interface->GetNetworkMask ()
+                << std::endl;
+    }
+
+  std::cout << "routing table:" << std::endl;
+  for (uint32_t i = 0; i < ipv4->GetNRoutes (); i++)
+    {
+      Ipv4Route *route = ipv4->GetRoute (i);
+      std::cout << (*route) << std::endl;
+    }
+  std::cout << "node end" << std::endl;
+}
+#endif
+
+int main (int argc, char *argv[])
+{
+#if 0
+  DebugComponentEnable("Queue");
+  DebugComponentEnable("DropTailQueue");
+  DebugComponentEnable("Channel");
+  DebugComponentEnable("SerialChannel");
+  DebugComponentEnable("SerialNetDevice");
+  DebugComponentEnable("SerialPhy");
+#endif
+
+  ObjectContainer container;
+
+  // The node factory is designed to allow user specification
+  // of the "type" of node desired for each node creation.  This
+  // is done by creating a node object (the inNode below), configuring
+  // the object with the desired capabilities, and pushing the node
+  // object on the prototype stack.  In this simple example, the
+  // default behavior of an InternetNode is adequate, so we don't
+  // do any configuration in this simple example.
+  InternetNode inNode;
+  Node::PushNodePrototype(inNode);
+  // Next create the physical node topology using the node factory
+  Node* n0 = Node::Create(); 
+  Node* n1 = Node::Create(); 
+  Node* n2 = Node::Create(); 
+  Node* n3 = Node::Create(); 
+
+  SerialChannel* ch1;
+  ch1 = SerialTopology::AddSerialLink (
+      n0, Ipv4Address("10.1.1.1"), 
+      n2, Ipv4Address("10.1.1.2"), 
+      5000000, MilliSeconds(2));
+  
+  SerialChannel* ch2;
+  ch2 = SerialTopology::AddSerialLink (
+      n1, Ipv4Address("10.1.2.1"), 
+      n2, Ipv4Address("10.1.2.2"), 
+      5000000, MilliSeconds(2));
+
+  SerialChannel* ch3;
+  ch3 = SerialTopology::AddSerialLink (
+      n2, Ipv4Address("10.1.3.1"), 
+      n3, Ipv4Address("10.1.3.2"), 
+      1500000, MilliSeconds(10));
+  
+  // To Do:
+  // avoid "new" calls, instead use application list
+  // OnOffSink
+  // use of rate and time objects
+  DatagramSocket *source0 = new DatagramSocket (n0);
+  DatagramSocket *source3 = new DatagramSocket (n3);
+  DatagramSocket *sink3 = new DatagramSocket(n3);
+  sink3->Bind (80);
+  DatagramSocket *sink1 = new DatagramSocket(n1);
+  sink1->Bind (80);
+
+#ifdef NOTYET
+  // This is functional and could soon replace the above DatagramSockets,
+  // but needs tuning
+  OnOffApplication* ooff = new OnOffApplication(*n0, Ipv4Address("10.1.2.2"), 
+  80, ConstantVariable(1), ConstantVariable(0), 1000, 210);
+  container.Acquire (ooff);
+  ooff->Start(Seconds(1.0));
+#endif
+
+  container.Acquire (source0);
+  container.Acquire (source3);
+  container.Acquire (sink3);
+  container.Acquire (sink1);
+
+  source3->SetDefaultDestination (Ipv4Address ("10.1.2.1"), 80);
+  source0->SetDefaultDestination (Ipv4Address ("10.1.3.2"), 80);
+
+  // Here, finish off packet routing configuration
+  n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
+  n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
+
+  AsciiTrace trace ("simple-p2p.tr");
+  trace.TraceAllQueues ();
+  trace.TraceAllNetDeviceRx ();
+
+  PrintTraffic (sink3);
+  GenerateTraffic (source0, 100);
+
+  PrintTraffic (sink1);
+  GenerateTraffic (source3, 100);
+
+  Simulator::StopAt (Seconds(10.0));
+
+  Simulator::Run ();
+    
+  // The below deletes will be managed by future topology objects
+  // or containers or smart pointers
+
+  Simulator::Destroy ();
+}
--- a/examples/simple-serial.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * ns-2 simple.tcl script (ported from ns-2)
- * Originally authored by Steve McCanne, 12/19/1996
- */
-
-// Port of ns-2/tcl/ex/simple.tcl to ns-3
-//
-// Network topology
-//
-//  n0
-//     \ 5 Mb/s, 2ms
-//      \          1.5Mb/s, 10ms
-//       n2 -------------------------n3
-//      /
-//     / 5 Mb/s, 2ms
-//   n1
-//
-// - all links are serial links with indicated one-way BW/delay
-// - CBR/UDP flows from n0 to n3, and from n3 to n1
-// - FTP/TCP flow from n0 to n3, starting at time 1.2 to time 1.35 sec.
-// - UDP packet size of 210 bytes, with per-packet interval 0.00375 sec.
-// - DropTail queues 
-// - Tracing of queues and packet receptions to file "out.tr"
-
-#include <iostream>
-#include <fstream>
-#include <string>
-#include <cassert>
-
-#include "ns3/debug.h"
-
-#include "ns3/simulator.h"
-#include "ns3/nstime.h"
-#include "ns3/trace-writer.h"
-
-#include "ns3/internet-node.h"
-#include "ns3/serial-channel.h"
-#include "ns3/serial-net-device.h"
-#include "ns3/mac-address.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/arp-ipv4-interface.h"
-#include "ns3/ipv4.h"
-#include "ns3/datagram-socket.h"
-#include "ns3/ipv4-route.h"
-#include "ns3/drop-tail.h"
-#include "ns3/trace-writer.h"
-#include "ns3/llc-snap-header.h"
-#include "ns3/arp-header.h"
-#include "ns3/ipv4-header.h"
-#include "ns3/udp-header.h"
-#include "ns3/node-list.h"
-#include "ns3/trace-root.h"
-#include "ns3/object-container.h"
-#include "ns3/serial-topology.h"
-#include "ns3/onoff-application.h"
-#include "ns3/random-variable.h"
-
-using namespace ns3;
-
-class AsciiTrace 
-{
-public:
-  AsciiTrace (std::string filename);
-  ~AsciiTrace ();
-  void TraceAllQueues (void);
-  void TraceAllNetDeviceRx (void);
-private:
-  void LogDevQueue (TraceContext const &context, const Packet &p);
-  void LogDevRx (TraceContext const &context, Packet &p);
-  std::ofstream m_os;
-};
-
-AsciiTrace::AsciiTrace (std::string filename)
-{
-  m_os.open (filename.c_str ());
-}
-AsciiTrace::~AsciiTrace ()
-{
-  m_os.close ();
-}
-void
-AsciiTrace::TraceAllQueues (void)
-{
-  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*",
-                      MakeCallback (&AsciiTrace::LogDevQueue, this));
-}
-void
-AsciiTrace::TraceAllNetDeviceRx (void)
-{
-  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/rx",
-                      MakeCallback (&AsciiTrace::LogDevRx, this));
-}
-
-void 
-AsciiTrace::LogDevQueue (TraceContext const &context, Packet const &p)
-{
-  enum Queue::TraceType type;
-  context.Get (type);
-  switch (type) 
-    {
-    case Queue::ENQUEUE:
-      m_os << "+ ";
-      break;
-    case Queue::DEQUEUE:
-      m_os << "- ";
-      break;
-    case Queue::DROP:
-      m_os << "d ";
-      break;
-    }
-  m_os << Simulator::Now ().GetSeconds () << " ";
-  NodeList::NodeIndex nodeIndex;
-  context.Get (nodeIndex);
-  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Ipv4::InterfaceIndex interfaceIndex;
-  context.Get (interfaceIndex);
-  m_os << "interface=" << interfaceIndex << " ";
-  m_os << "pkt-uid=" << p.GetUid () << " ";
-  m_os << std::endl;
-}
-void 
-AsciiTrace::LogDevRx (TraceContext const &context, Packet &p)
-{
-  m_os << "r " << Simulator::Now ().GetSeconds () << " ";
-  NodeList::NodeIndex nodeIndex;
-  context.Get (nodeIndex);
-  m_os << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-  Ipv4::InterfaceIndex interfaceIndex;
-  context.Get (interfaceIndex);
-  m_os << "interface=" << interfaceIndex << " ";
-  m_os << "pkt-uid=" << p.GetUid () << " ";
-  m_os << std::endl;  
-}
-
-
-static void
-GenerateTraffic (DatagramSocket *socket, uint32_t size)
-{
-  std::cout << "Node: " << socket->GetNode()->GetId () 
-            << " at=" << Simulator::Now ().GetSeconds () << "s,"
-            << " tx bytes=" << size << std::endl;
-  socket->SendDummy (size);
-  if (size > 50)
-    {
-      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
-    }
-}
-
-static void
-DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
-{
-  std::cout << "Node: " << socket->GetNode()->GetId () 
-            << " at=" << Simulator::Now ().GetSeconds () << "s,"
-            << " rx bytes=" << size << std::endl;
-}
-
-static void
-PrintTraffic (DatagramSocket *socket)
-{
-  socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
-}
-
-#if 0
-static void
-PrintRoutingTable (InternetNode *a, std::string name)
-{
-  Ipv4 *ipv4 = a->GetIpv4 ();
-  std::cout << "interfaces node="<<name<<std::endl;
-  for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
-    {
-      Ipv4Interface *interface = ipv4->GetInterface (i);
-      std::cout << "interface addr="<<interface->GetAddress () 
-                << ", netmask="<<interface->GetNetworkMask ()
-                << std::endl;
-    }
-
-  std::cout << "routing table:" << std::endl;
-  for (uint32_t i = 0; i < ipv4->GetNRoutes (); i++)
-    {
-      Ipv4Route *route = ipv4->GetRoute (i);
-      std::cout << (*route) << std::endl;
-    }
-  std::cout << "node end" << std::endl;
-}
-#endif
-
-int main (int argc, char *argv[])
-{
-#if 0
-  DebugComponentEnable("Queue");
-  DebugComponentEnable("DropTailQueue");
-  DebugComponentEnable("Channel");
-  DebugComponentEnable("SerialChannel");
-  DebugComponentEnable("SerialNetDevice");
-  DebugComponentEnable("SerialPhy");
-#endif
-
-  ObjectContainer container;
-
-  // The node factory is designed to allow user specification
-  // of the "type" of node desired for each node creation.  This
-  // is done by creating a node object (the inNode below), configuring
-  // the object with the desired capabilities, and pushing the node
-  // object on the prototype stack.  In this simple example, the
-  // default behavior of an InternetNode is adequate, so we don't
-  // do any configuration in this simple example.
-  InternetNode inNode;
-  Node::PushNodePrototype(inNode);
-  // Next create the physical node topology using the node factory
-  Node* n0 = Node::Create(); 
-  Node* n1 = Node::Create(); 
-  Node* n2 = Node::Create(); 
-  Node* n3 = Node::Create(); 
-
-  SerialChannel* ch1;
-  ch1 = SerialTopology::AddSerialLink (
-      n0, Ipv4Address("10.1.1.1"), 
-      n2, Ipv4Address("10.1.1.2"), 
-      5000000, MilliSeconds(2));
-  
-  SerialChannel* ch2;
-  ch2 = SerialTopology::AddSerialLink (
-      n1, Ipv4Address("10.1.2.1"), 
-      n2, Ipv4Address("10.1.2.2"), 
-      5000000, MilliSeconds(2));
-
-  SerialChannel* ch3;
-  ch3 = SerialTopology::AddSerialLink (
-      n2, Ipv4Address("10.1.3.1"), 
-      n3, Ipv4Address("10.1.3.2"), 
-      1500000, MilliSeconds(10));
-  
-  // To Do:
-  // avoid "new" calls, instead use application list
-  // OnOffSink
-  // use of rate and time objects
-  DatagramSocket *source0 = new DatagramSocket (n0);
-  DatagramSocket *source3 = new DatagramSocket (n3);
-  DatagramSocket *sink3 = new DatagramSocket(n3);
-  sink3->Bind (80);
-  DatagramSocket *sink1 = new DatagramSocket(n1);
-  sink1->Bind (80);
-
-#ifdef NOTYET
-  // This is functional and could soon replace the above DatagramSockets,
-  // but needs tuning
-  OnOffApplication* ooff = new OnOffApplication(*n0, Ipv4Address("10.1.2.2"), 
-  80, ConstantVariable(1), ConstantVariable(0), 1000, 210);
-  container.Acquire (ooff);
-  ooff->Start(Seconds(1.0));
-#endif
-
-  container.Acquire (source0);
-  container.Acquire (source3);
-  container.Acquire (sink3);
-  container.Acquire (sink1);
-
-  source3->SetDefaultDestination (Ipv4Address ("10.1.2.1"), 80);
-  source0->SetDefaultDestination (Ipv4Address ("10.1.3.2"), 80);
-
-  // Here, finish off packet routing configuration
-  n0->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
-  n3->GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.3.1"), 1);
-
-  AsciiTrace trace ("simple-serial.tr");
-  trace.TraceAllQueues ();
-  trace.TraceAllNetDeviceRx ();
-
-  PrintTraffic (sink3);
-  GenerateTraffic (source0, 100);
-
-  PrintTraffic (sink1);
-  GenerateTraffic (source3, 100);
-
-  Simulator::StopAt (Seconds(10.0));
-
-  Simulator::Run ();
-    
-  // The below deletes will be managed by future topology objects
-  // or containers or smart pointers
-
-  Simulator::Destroy ();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/samples/main-p2p-net-device-if.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,241 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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
+ */
+
+#if 0
+#include <list>
+#include <cassert>
+#endif
+
+#include "ns3/debug.h"
+#include "ns3/internet-node.h"
+#include "ns3/packet.h"
+#include "ns3/arp-ipv4-interface.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/p2p-channel.h"
+#include "ns3/p2p-net-device.h"
+#include "ns3/trace-writer.h"
+#include "ns3/drop-tail.h"
+#include "ns3/arp-ipv4-interface.h"
+#include "ns3/ipv4.h"
+#include "ns3/trace-context.h"
+#include "ns3/datagram-socket.h"
+#include "ns3/simulator.h"
+#include "ns3/node-list.h"
+#include "ns3/trace-root.h"
+
+
+using namespace ns3;
+
+class Logger : public TraceWriter{
+public:
+  Logger ()
+  {
+    NS_DEBUG_UNCOND("**** Logger()");
+  }
+
+  Logger (std::string const &filename) 
+  {
+    NS_DEBUG_UNCOND("**** Logger(string const &)");
+    Open(filename);
+  }
+
+  Logger (char const *filename) : m_tracer(filename)
+  {
+    NS_DEBUG_UNCOND("**** Logger(char const *)");
+    Open(filename);
+  }
+
+  ~Logger () {}
+
+  void Log (TraceContext const &context, const Packet &p)
+  {
+    NodeList::NodeIndex nodeIndex;
+    context.Get (nodeIndex);
+    m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
+    Ipv4::InterfaceIndex interfaceIndex;
+    context.Get (interfaceIndex);
+    m_filestr << "interface=" << interfaceIndex << " ";
+    enum Queue::TraceType type;
+    context.Get (type);
+    switch (type) 
+      {
+      case Queue::ENQUEUE:
+        m_filestr << "enqueue";
+        break;
+      case Queue::DEQUEUE:
+        m_filestr << "dequeue";
+        break;
+      case Queue::DROP:
+        m_filestr << "drop";
+        break;
+      }
+    m_filestr << " bytes=" << p.GetSize () << std::endl;
+  }
+
+protected:
+  TraceWriter m_tracer;
+};
+
+static void
+GenerateTraffic (DatagramSocket *socket, uint32_t size)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " tx bytes=" << size << std::endl;
+  socket->SendDummy (size);
+  if (size > 50)
+    {
+      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
+    }
+}
+
+static void
+DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
+{
+  std::cout << "Node: " << socket->GetNode()->GetId () 
+            << " at=" << Simulator::Now ().GetSeconds () << "s,"
+            << " rx bytes=" << size << std::endl;
+}
+
+static void
+PrintTraffic (DatagramSocket *socket)
+{
+  socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
+}
+
+
+int main (int argc, char *argv[])
+{
+  NS_DEBUG_UNCOND("Serial Net Device Test");
+
+  // create two nodes and a simple SerialChannel
+  InternetNode a;
+  InternetNode b;
+  SerialChannel ch = SerialChannel ("Test Channel", 1000, Seconds (0.1));
+
+  NodeList::Add (&a);
+  NodeList::Add (&b);
+
+  // create two NetDevices and assign one to each node
+  // Note:  this would normally be done also in conjunction with
+  //        creating a Channel
+   
+  SerialNetDevice neta(&a);
+
+  DropTailQueue dtqa;
+
+  neta.AddQueue(&dtqa);
+  neta.SetName("a.eth0"); 
+
+  SerialNetDevice netb(&b);
+
+  DropTailQueue dtqb;
+
+  netb.AddQueue(&dtqb);
+  netb.SetName("b.eth0"); 
+
+  // bind the two NetDevices together by using a simple Channel
+  // this method changed to do a bidirectional binding
+  neta.Attach (&ch);
+  netb.Attach (&ch);
+
+  // Some simple prints to see whether it is working
+  NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
+  NS_DEBUG_UNCOND("netb.GetMtu() <= " << netb.GetMtu());
+  NS_DEBUG_UNCOND("neta.GetAddress() <= " << neta.GetAddress());
+  NS_DEBUG_UNCOND("netb.GetAddress() <= " << netb.GetAddress());
+
+  // Note:  InternetNode constructor instantiates multiple Layer-3
+  // protocols and registers them with the L3Demux object.
+  // This takes care of Layer-2 -> Layer-3 bindings.
+  //  XXX TODO:  will need to create a dummy IPv4 object for insertion
+  //             into the Demux
+
+  // We now need to bind the InternetNode to the various interfaces.
+  // to get the Layer-3 -> Layer-2 bindings.
+
+  // We do this by calling an "AddArpIpv4Interface(neta)" function on node a.
+  // This should:  
+  // i) create an Ipv4ArpInterface object (subclass of pure virtual
+  //    Ipv4Interface object)
+  // ii) add the Ipv4ArpInterface object to the InternetNode's internal
+  //     vector of Ipv4Interfaces (keyed off of ifIndex)
+
+  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode a");
+  ArpIpv4Interface* arpipv4interfacep = new ArpIpv4Interface(&a, &neta);
+  uint32_t indexA = (&a)->GetIpv4 ()->AddInterface (arpipv4interfacep);
+  NS_DEBUG_UNCOND("Adding Interface " << indexA);
+
+
+  // iii) give the interface an IP address
+
+  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
+  arpipv4interfacep->SetAddress(Ipv4Address("10.1.1.1"));
+  arpipv4interfacep->SetNetworkMask(Ipv4Mask("255.255.255.0"));
+
+  // iv) set the interface's state to "UP"
+
+  NS_DEBUG_UNCOND("Setting ARP interface to UP");
+  arpipv4interfacep->SetUp();
+
+  a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
+
+
+  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
+  ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
+  uint32_t indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
+  NS_DEBUG_UNCOND("Adding Interface " << indexB);
+
+
+  // iii) give the interface an IP address
+
+  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
+  arpipv4interfacepb->SetAddress(Ipv4Address("10.1.1.2"));
+  arpipv4interfacepb->SetNetworkMask(Ipv4Mask("255.255.255.0"));
+
+  // iv) set the interface's state to "UP"
+
+  NS_DEBUG_UNCOND("Setting ARP interface to UP");
+  arpipv4interfacepb->SetUp();
+
+  b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
+
+
+  DatagramSocket *source = new DatagramSocket (&a);
+  DatagramSocket *sink = new DatagramSocket(&b);
+  sink->Bind (80);
+  source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
+
+  Logger logger("p2p-net-test.log");
+
+  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*", 
+                      MakeCallback (&Logger::Log, &logger));
+
+  PrintTraffic (sink);
+  GenerateTraffic (source, 100);
+
+  Simulator::Run ();
+
+  Simulator::Destroy ();
+
+  delete source;
+  delete sink;
+
+  return 0;
+}
--- a/samples/main-serial-net-device-if.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- * 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
- */
-
-#if 0
-#include <list>
-#include <cassert>
-#endif
-
-#include "ns3/debug.h"
-#include "ns3/internet-node.h"
-#include "ns3/packet.h"
-#include "ns3/arp-ipv4-interface.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/serial-channel.h"
-#include "ns3/serial-net-device.h"
-#include "ns3/trace-writer.h"
-#include "ns3/drop-tail.h"
-#include "ns3/arp-ipv4-interface.h"
-#include "ns3/ipv4.h"
-#include "ns3/trace-context.h"
-#include "ns3/datagram-socket.h"
-#include "ns3/simulator.h"
-#include "ns3/node-list.h"
-#include "ns3/trace-root.h"
-
-
-using namespace ns3;
-
-class Logger : public TraceWriter{
-public:
-  Logger ()
-  {
-    NS_DEBUG_UNCOND("**** Logger()");
-  }
-
-  Logger (std::string const &filename) 
-  {
-    NS_DEBUG_UNCOND("**** Logger(string const &)");
-    Open(filename);
-  }
-
-  Logger (char const *filename) : m_tracer(filename)
-  {
-    NS_DEBUG_UNCOND("**** Logger(char const *)");
-    Open(filename);
-  }
-
-  ~Logger () {}
-
-  void Log (TraceContext const &context, const Packet &p)
-  {
-    NodeList::NodeIndex nodeIndex;
-    context.Get (nodeIndex);
-    m_filestr << "node=" << NodeList::GetNode (nodeIndex)->GetId () << " ";
-    Ipv4::InterfaceIndex interfaceIndex;
-    context.Get (interfaceIndex);
-    m_filestr << "interface=" << interfaceIndex << " ";
-    enum Queue::TraceType type;
-    context.Get (type);
-    switch (type) 
-      {
-      case Queue::ENQUEUE:
-        m_filestr << "enqueue";
-        break;
-      case Queue::DEQUEUE:
-        m_filestr << "dequeue";
-        break;
-      case Queue::DROP:
-        m_filestr << "drop";
-        break;
-      }
-    m_filestr << " bytes=" << p.GetSize () << std::endl;
-  }
-
-protected:
-  TraceWriter m_tracer;
-};
-
-static void
-GenerateTraffic (DatagramSocket *socket, uint32_t size)
-{
-  std::cout << "Node: " << socket->GetNode()->GetId () 
-            << " at=" << Simulator::Now ().GetSeconds () << "s,"
-            << " tx bytes=" << size << std::endl;
-  socket->SendDummy (size);
-  if (size > 50)
-    {
-      Simulator::Schedule (Seconds (0.5), &GenerateTraffic, socket, size - 50);
-    }
-}
-
-static void
-DatagramSocketPrinter (DatagramSocket *socket, uint32_t size, Ipv4Address from, uint16_t fromPort)
-{
-  std::cout << "Node: " << socket->GetNode()->GetId () 
-            << " at=" << Simulator::Now ().GetSeconds () << "s,"
-            << " rx bytes=" << size << std::endl;
-}
-
-static void
-PrintTraffic (DatagramSocket *socket)
-{
-  socket->SetDummyRxCallback (MakeCallback (&DatagramSocketPrinter));
-}
-
-
-int main (int argc, char *argv[])
-{
-  NS_DEBUG_UNCOND("Serial Net Device Test");
-
-  // create two nodes and a simple SerialChannel
-  InternetNode a;
-  InternetNode b;
-  SerialChannel ch = SerialChannel ("Test Channel", 1000, Seconds (0.1));
-
-  NodeList::Add (&a);
-  NodeList::Add (&b);
-
-  // create two NetDevices and assign one to each node
-  // Note:  this would normally be done also in conjunction with
-  //        creating a Channel
-   
-  SerialNetDevice neta(&a);
-
-  DropTailQueue dtqa;
-
-  neta.AddQueue(&dtqa);
-  neta.SetName("a.eth0"); 
-
-  SerialNetDevice netb(&b);
-
-  DropTailQueue dtqb;
-
-  netb.AddQueue(&dtqb);
-  netb.SetName("b.eth0"); 
-
-  // bind the two NetDevices together by using a simple Channel
-  // this method changed to do a bidirectional binding
-  neta.Attach (&ch);
-  netb.Attach (&ch);
-
-  // Some simple prints to see whether it is working
-  NS_DEBUG_UNCOND("neta.GetMtu() <= " << neta.GetMtu());
-  NS_DEBUG_UNCOND("netb.GetMtu() <= " << netb.GetMtu());
-  NS_DEBUG_UNCOND("neta.GetAddress() <= " << neta.GetAddress());
-  NS_DEBUG_UNCOND("netb.GetAddress() <= " << netb.GetAddress());
-
-  // Note:  InternetNode constructor instantiates multiple Layer-3
-  // protocols and registers them with the L3Demux object.
-  // This takes care of Layer-2 -> Layer-3 bindings.
-  //  XXX TODO:  will need to create a dummy IPv4 object for insertion
-  //             into the Demux
-
-  // We now need to bind the InternetNode to the various interfaces.
-  // to get the Layer-3 -> Layer-2 bindings.
-
-  // We do this by calling an "AddArpIpv4Interface(neta)" function on node a.
-  // This should:  
-  // i) create an Ipv4ArpInterface object (subclass of pure virtual
-  //    Ipv4Interface object)
-  // ii) add the Ipv4ArpInterface object to the InternetNode's internal
-  //     vector of Ipv4Interfaces (keyed off of ifIndex)
-
-  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode a");
-  ArpIpv4Interface* arpipv4interfacep = new ArpIpv4Interface(&a, &neta);
-  uint32_t indexA = (&a)->GetIpv4 ()->AddInterface (arpipv4interfacep);
-  NS_DEBUG_UNCOND("Adding Interface " << indexA);
-
-
-  // iii) give the interface an IP address
-
-  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
-  arpipv4interfacep->SetAddress(Ipv4Address("10.1.1.1"));
-  arpipv4interfacep->SetNetworkMask(Ipv4Mask("255.255.255.0"));
-
-  // iv) set the interface's state to "UP"
-
-  NS_DEBUG_UNCOND("Setting ARP interface to UP");
-  arpipv4interfacep->SetUp();
-
-  a.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.2"), 1);
-
-
-  NS_DEBUG_UNCOND("Adding ARP Interface to InternetNode b");
-  ArpIpv4Interface* arpipv4interfacepb = new ArpIpv4Interface(&b, &netb);
-  uint32_t indexB = (&b)->GetIpv4 ()->AddInterface (arpipv4interfacepb);
-  NS_DEBUG_UNCOND("Adding Interface " << indexB);
-
-
-  // iii) give the interface an IP address
-
-  NS_DEBUG_UNCOND("Giving IP address to ARP Interface");
-  arpipv4interfacepb->SetAddress(Ipv4Address("10.1.1.2"));
-  arpipv4interfacepb->SetNetworkMask(Ipv4Mask("255.255.255.0"));
-
-  // iv) set the interface's state to "UP"
-
-  NS_DEBUG_UNCOND("Setting ARP interface to UP");
-  arpipv4interfacepb->SetUp();
-
-  b.GetIpv4()->SetDefaultRoute (Ipv4Address ("10.1.1.1"), 1);
-
-
-  DatagramSocket *source = new DatagramSocket (&a);
-  DatagramSocket *sink = new DatagramSocket(&b);
-  sink->Bind (80);
-  source->SetDefaultDestination (Ipv4Address ("10.1.1.2"), 80);
-
-  Logger logger("serial-net-test.log");
-
-  TraceRoot::Connect ("/nodes/*/ipv4/interfaces/*/netdevice/queue/*", 
-                      MakeCallback (&Logger::Log, &logger));
-
-  PrintTraffic (sink);
-  GenerateTraffic (source, 100);
-
-  Simulator::Run ();
-
-  Simulator::Destroy ();
-
-  delete source;
-  delete sink;
-
-  return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p-gfr/p2p-channel.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,98 @@
+// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Implementation of simple point-to-point channel
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include "ns3/simulator.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "p2p-channel.h"
+#include "p2p-net-device.h"
+
+namespace ns3 {
+
+P2PChannel::P2PChannel(const Time& delay, double maxRate) 
+  : m_nd1(0), m_nd2(0),
+    m_delay (delay),
+    m_maxRate (maxRate)
+{
+}
+
+P2PChannel::~P2PChannel ()
+{}
+
+// Channels create compatible net devices
+P2PNetDevice* P2PChannel::CreateNetDevice(Node *node, MacAddress address)
+{
+  // Create a new point-to-point network device
+  P2PNetDevice* nd = new P2PNetDevice(node, address);
+  nd->Connect (this);
+  // Add to list of peers
+  if (!m_nd1) m_nd1 = nd;
+  else m_nd2 = nd;
+  return nd;
+}
+
+void P2PChannel::RemoveNetDevice(NetDevice* nd)
+{
+  if (nd == m_nd1) m_nd1 = 0;
+  if (nd == m_nd2) m_nd2 = 0;
+  // Now if all removed, remove the channel as well
+  if (!m_nd1 && !m_nd2)
+    {
+      delete this;
+    }
+}
+
+void P2PChannel::Send(P2PNetDevice *device, Packet& p, double rate)
+{ // Schedule a receive event at receiver
+  // First calculate time in future
+  double maxRate;
+  if (rate < m_maxRate)
+    {
+      maxRate = rate;
+    } 
+  else
+    {
+      maxRate = m_maxRate;
+    }
+  Time txTime = Seconds (p.GetSize() * 8 / maxRate);
+  Time rxTime = m_delay + txTime;
+  P2PNetDevice *to, *from;
+  if (device == m_nd1)
+    {
+      from = m_nd1;
+      to = m_nd2;
+    }
+  else
+    {
+      from = m_nd2;
+      to = m_nd1;
+    }
+  // Schedule the receive event at receiver
+  Simulator::Schedule(rxTime, &P2PNetDevice::Receive, to, p);
+  // Schedule the link free event
+  Simulator::Schedule(txTime, &P2PNetDevice::TxComplete, from);
+
+}
+
+}//namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p-gfr/p2p-channel.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,56 @@
+// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Definition of a simple point-to-point channel
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef P2P_CHANNEL_H
+#define P2P_CHANNEL_H
+
+#include "ns3/nstime.h"
+#include "ns3/mac-address.h"
+
+namespace ns3 {
+
+class P2PNetDevice;
+class NetDevice;
+class Node;
+class Packet;
+
+class P2PChannel  {
+public:
+  P2PChannel(const Time& delay, double maxRate /* bits/s */);
+  ~P2PChannel();
+
+  P2PNetDevice* CreateNetDevice(Node *node, MacAddress address);
+  void       RemoveNetDevice (NetDevice *device);
+  void       Send (P2PNetDevice *device, Packet&p, double rate /* bits/s */);
+private:
+  // The two endpoints of this channel
+  P2PNetDevice* m_nd1;
+  P2PNetDevice* m_nd2;
+  Time          m_delay;
+  double        m_maxRate;
+};
+
+}//namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p-gfr/p2p-net-device.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,80 @@
+// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Implementation of a point-to-point network device
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include "ns3/empty-trace-resolver.h"
+#include "p2p-net-device.h"
+#include "p2p-channel.h"
+
+namespace ns3 {
+
+P2PNetDevice::P2PNetDevice (Node *node, MacAddress const &addr)
+  : NetDevice (node, addr),
+    m_rate (1000000)
+{
+  SetMtu (2300);
+  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+}
+
+P2PNetDevice::~P2PNetDevice()
+{ // Inform channel that we are destroyed
+  m_channel->RemoveNetDevice(this);
+}
+
+void 
+P2PNetDevice::SetRate (double rate)
+{
+  m_rate = rate;
+}
+
+void 
+P2PNetDevice::Connect (P2PChannel *channel)
+{
+  m_channel = channel;
+  NotifyLinkUp ();
+}
+
+bool 
+P2PNetDevice::SendTo (Packet& p, const MacAddress&)
+{
+  m_channel->Send (this, p, m_rate);
+  return true;
+}
+
+TraceResolver *
+P2PNetDevice::DoCreateTraceResolver (TraceContext const &context)
+{
+  return new EmptyTraceResolver (context);
+}
+
+void
+P2PNetDevice::Receive(Packet p)
+{
+  ForwardUp (p);
+}
+
+void 
+P2PNetDevice::TxComplete (void)
+{}
+
+}//namespace ns3  
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p-gfr/p2p-net-device.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,54 @@
+// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+// Definition for a Point-to-Point network device
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef P2P_NET_DEVICE_H
+#define P2P_NET_DEVICE_H
+
+#include "ns3/net-device.h"
+
+namespace ns3 {
+
+class P2PChannel;
+
+class P2PNetDevice : public NetDevice {
+public:
+  P2PNetDevice(Node *node, MacAddress const &addr);
+  virtual ~P2PNetDevice();
+
+  void SetRate (double rate);
+  void Connect (P2PChannel *channel);
+  void Receive(Packet p);
+  void TxComplete (void);
+ private:
+  virtual bool SendTo (Packet& p, const MacAddress& dest);
+  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
+
+  double m_rate;
+  P2PChannel *m_channel;
+};
+
+}//namespace ns3
+
+#endif /* P2P_NET_DEVICE_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/layer-connector.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,138 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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: Craig Dowell <craigdo@ee.washingon.edu>
+ *
+ *      Fri Feb 16 12:18:11 PST 2007 craigdo:  created
+ */
+
+#include "ns3/debug.h"
+#include "ns3/assert.h"
+#include "layer-connector.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("LayerConnector");
+
+namespace ns3 {
+
+LayerConnectorUpper::LayerConnectorUpper ()
+{
+  NS_DEBUG("LayerConnectorUpper::LayerConnectorUpper ()");
+}
+
+LayerConnectorUpper::~LayerConnectorUpper ()
+{
+  NS_DEBUG("LayerConnectorUpper::~LayerConnectorUpper ()");
+}
+
+  bool
+LayerConnectorUpper::ConnectToLower (LayerConnectorLower &partner)
+{
+  NS_DEBUG("LayerConnectorUpper::ConnectToLower (" << &partner << ")");
+
+  return DoConnectToLower(partner);
+}
+
+  bool
+LayerConnectorUpper::DoConnectToLower (LayerConnectorLower &partner)
+{
+  NS_DEBUG("LayerConnectorUpper::DoConnectToLower (" << &partner << ")");
+
+  m_lowerPartner = &partner;
+  NS_ASSERT (m_lowerPartner);
+  return true;
+}
+
+  bool
+LayerConnectorUpper::UpperSendUp (Packet &p)
+{
+  NS_DEBUG("LayerConnectorUpper::UpperSendUp (" << &p << ")");
+
+  return UpperDoSendUp(p);
+}
+
+  bool
+LayerConnectorUpper::UpperPull (Packet &p)
+{
+  NS_DEBUG("LayerConnectorUpper::UpperPull (" << &p << ")");
+
+  return UpperDoPull(p);
+}
+
+  bool
+LayerConnectorUpper::UpperNotify ()
+{
+  NS_DEBUG("LayerConnectorUpper::UpperNotify ()");
+
+  NS_ASSERT (m_lowerPartner);
+  return m_lowerPartner->LowerNotify(this);
+}
+
+LayerConnectorLower::LayerConnectorLower ()
+{
+  NS_DEBUG("LayerConnectorLower::LayerConnectorLower ()");
+}
+
+LayerConnectorLower::~LayerConnectorLower ()
+{
+  NS_DEBUG("LayerConnectorLower::~LayerConnectorLower ()");
+}
+
+  bool
+LayerConnectorLower::ConnectToUpper (LayerConnectorUpper &partner)
+{
+  NS_DEBUG("LayerConnectorLower::ConnectToUpper (" << &partner << ")");
+
+  return DoConnectToUpper(partner);
+}
+
+  bool
+LayerConnectorLower::DoConnectToUpper (LayerConnectorUpper &partner)
+{
+  NS_DEBUG("LayerConnectorLower::DoConnectToUpper (" << &partner << ")");
+
+  m_upperPartner = &partner;
+  NS_ASSERT (m_upperPartner);
+  return true;
+}
+
+  bool
+LayerConnectorLower::LowerSendUp (Packet &p)
+{
+  NS_DEBUG("LayerConnectorLower::LowerSendUp (" << &p << ")");
+
+  NS_ASSERT (m_upperPartner);
+  return m_upperPartner->UpperSendUp(p);
+}
+
+  bool
+LayerConnectorLower::LowerPull (Packet &p)
+{
+  NS_DEBUG("LayerConnectorLower::LowerPull (" << &p << ")");
+
+  NS_ASSERT (m_upperPartner);
+  return m_upperPartner->UpperPull(p);
+}
+
+  bool
+LayerConnectorLower::LowerNotify (LayerConnectorUpper *upper)
+{
+  NS_DEBUG("LayerConnectorLower::LowerNotify ()");
+  return LowerDoNotify(upper);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/layer-connector.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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: Craig Dowell <craigdo@ee.washingon.edu>
+ *
+ *      Wed Feb 14 16:05:46 PST 2007 craigdo:  created
+ */
+
+#include "ns3/packet.h"
+
+#ifndef LAYER_CONNECTOR_H
+#define LAYER_CONNECTOR_H
+
+namespace ns3 {
+
+class LayerConnectorLower;
+
+class LayerConnectorUpper {
+public:
+  LayerConnectorUpper ();
+  virtual ~LayerConnectorUpper ();
+
+  // called by the layer connector to introduce the lower interface to us here
+  bool ConnectToLower (LayerConnectorLower &lower);
+
+  // called by the lower layer to send a received packet on up the protocol
+  // stack to us here.
+  bool UpperSendUp (Packet &p);
+
+  // Call this function to tell a lower layer that there is data available
+  // here.  It is expected that the lower layer will call pull as soon as
+  // possible to get the data.
+  bool UpperNotify ();
+
+  // called by the lower layer to get available packet data that was implied
+  // by a previous Notify() call.
+  bool UpperPull(Packet &p);
+
+protected:
+  virtual bool DoConnectToLower (LayerConnectorLower &lower);
+  virtual bool UpperDoSendUp (Packet &p) = 0;
+  virtual bool UpperDoPull (Packet &p) = 0;
+
+  LayerConnectorLower *m_lowerPartner;
+
+private:
+};
+
+class LayerConnectorLower
+{
+public:
+  LayerConnectorLower ();
+  virtual ~LayerConnectorLower ();
+
+  // This function is called by the layer connector to introduce the upper
+  // layer interface to us here
+  bool ConnectToUpper (LayerConnectorUpper &upper);
+
+  // Notify is called by the upper layer connector to tell us that there
+  // is data available.  It is expected that we will call pull (below) as
+  // soon as possible to get the data.
+  bool LowerNotify (LayerConnectorUpper *upper);
+
+  // The lower connector calls this method to send a received packet on up 
+  // the protocol stack
+  bool LowerSendUp (Packet &p);
+
+  // Call this function to get available packet data from the upper connector
+  // that was implied by a previous Notify() call.
+  bool LowerPull(Packet &p);
+
+protected:
+  virtual bool DoConnectToUpper (LayerConnectorUpper &upper);
+  virtual bool LowerDoNotify (LayerConnectorUpper *upper) = 0;
+  LayerConnectorUpper *m_upperPartner;
+
+private:
+};
+
+}; // namespace ns3
+
+#endif /* LAYER_CONNECTOR_H */
--- a/src/devices/p2p/p2p-channel.cc	Sun Mar 25 06:43:34 2007 -0700
+++ b/src/devices/p2p/p2p-channel.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -1,98 +1,160 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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: Craig Dowell <craigdo@ee.washington.edu>
+ */
 
-// Implementation of simple point-to-point channel
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ns3/simulator.h"
-#include "ns3/packet.h"
-#include "ns3/node.h"
 #include "p2p-channel.h"
 #include "p2p-net-device.h"
+#include "p2p-phy.h"
+#include "ns3/packet.h"
+#include "ns3/simulator.h"
+#include "ns3/debug.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("SerialChannel");
 
 namespace ns3 {
 
-P2PChannel::P2PChannel(const Time& delay, double maxRate) 
-  : m_nd1(0), m_nd2(0),
-    m_delay (delay),
-    m_maxRate (maxRate)
+//
+// By default, you get a channel with the name "Serial Channel" that has an
+// "infitely" fast transmission speed and zero delay.
+// XXX: this does not work because m_bps = 0 results in infinitely slow transmission
+// speed. 
+SerialChannel::SerialChannel()
+: 
+  Channel ("Serial Channel"), 
+  m_bps (0),
+  m_delay (Seconds(0)),
+  m_nDevices(0)
 {
+  NS_DEBUG("SerialChannel::SerialChannel ()");
+}
+
+SerialChannel::SerialChannel(
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel ("Serial Channel"), 
+  m_bps (bps), 
+  m_delay (delay),
+  m_nDevices(0)
+{
+  NS_DEBUG("SerialChannel::SerialChannel (" << Channel::GetName() << ", " << bps << ", " << 
+    delay << ")");
 }
 
-P2PChannel::~P2PChannel ()
-{}
-
-// Channels create compatible net devices
-P2PNetDevice* P2PChannel::CreateNetDevice(Node *node, MacAddress address)
+SerialChannel::SerialChannel(
+  const std::string& name,
+  const DataRate& bps, 
+  const Time& delay)
+: 
+  Channel (name),
+  m_bps (bps), 
+  m_delay (delay),
+  m_nDevices(0)
 {
-  // Create a new point-to-point network device
-  P2PNetDevice* nd = new P2PNetDevice(node, address);
-  nd->Connect (this);
-  // Add to list of peers
-  if (!m_nd1) m_nd1 = nd;
-  else m_nd2 = nd;
-  return nd;
+  NS_DEBUG("SerialChannel::SerialChannel (" << name << ", " << bps << ", " << 
+    delay << ")");
 }
 
-void P2PChannel::RemoveNetDevice(NetDevice* nd)
+  void
+SerialChannel::Attach(SerialPhy *phy)
 {
-  if (nd == m_nd1) m_nd1 = 0;
-  if (nd == m_nd2) m_nd2 = 0;
-  // Now if all removed, remove the channel as well
-  if (!m_nd1 && !m_nd2)
+  NS_DEBUG("SerialChannel::Attach (" << phy << ")");
+  NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
+  NS_ASSERT(phy);
+
+  m_link[m_nDevices].m_src = phy;
+  ++m_nDevices;
+//
+// If we have both devices connected to the channel, then finish introducing
+// the two halves and set the links to IDLE.
+//
+  if (m_nDevices == N_DEVICES)
     {
-      delete this;
+      m_link[0].m_dst = m_link[1].m_src;
+      m_link[1].m_dst = m_link[0].m_src;
+      m_link[0].m_state = IDLE;
+      m_link[1].m_state = IDLE;
     }
 }
 
-void P2PChannel::Send(P2PNetDevice *device, Packet& p, double rate)
-{ // Schedule a receive event at receiver
-  // First calculate time in future
-  double maxRate;
-  if (rate < m_maxRate)
-    {
-      maxRate = rate;
-    } 
-  else
-    {
-      maxRate = m_maxRate;
-    }
-  Time txTime = Seconds (p.GetSize() * 8 / maxRate);
-  Time rxTime = m_delay + txTime;
-  P2PNetDevice *to, *from;
-  if (device == m_nd1)
-    {
-      from = m_nd1;
-      to = m_nd2;
-    }
-  else
-    {
-      from = m_nd2;
-      to = m_nd1;
-    }
-  // Schedule the receive event at receiver
-  Simulator::Schedule(rxTime, &P2PNetDevice::Receive, to, p);
-  // Schedule the link free event
-  Simulator::Schedule(txTime, &P2PNetDevice::TxComplete, from);
+void
+SerialChannel::TransmitCompleteEvent(Packet p, SerialPhy *src)
+{
+  NS_DEBUG("SerialChannel::TransmitCompleteEvent (" << &p << ", " << 
+    src << ")");
 
+  NS_ASSERT(m_link[0].m_state != INITIALIZING);
+  NS_ASSERT(m_link[1].m_state != INITIALIZING);
+  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
+  NS_ASSERT(m_link[wire].m_state == TRANSMITTING);
+
+  m_link[wire].m_state = IDLE;
+  
+  NS_DEBUG("SerialChannel::TransmitCompleteEvent (): Receive()");
+
+  m_link[wire].m_dst->Receive (p);
 }
 
-}//namespace ns3
+bool
+SerialChannel::Propagate(Packet& p, SerialPhy* src)
+{
+  NS_DEBUG("SerialChannel::DoPropagate (" << &p << ", " << src << ")");
+
+  NS_ASSERT(m_link[0].m_state != INITIALIZING);
+  NS_ASSERT(m_link[1].m_state != INITIALIZING);
+
+  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
+
+  if (m_link[wire].m_state == TRANSMITTING)
+    {
+      NS_DEBUG("SerialChannel::DoPropagate (): TRANSMITTING, return");
+      return false;
+    }
+
+  m_link[wire].m_state = TRANSMITTING;
+
+//
+// I believe Raj has a method in the DataRate class to do this.  Should use
+// it when it is available.
+//
+  Time tEvent =  Seconds (static_cast<double> (p.GetSize() * 8) / 
+                          static_cast<double> (m_bps)) + m_delay;
+
+  NS_DEBUG("SerialChannel::DoSend (): Schedule Receive delay " << tEvent);
+
+  Packet packet = p;
+  Simulator::Schedule (tEvent, &SerialChannel::TransmitCompleteEvent, this, 
+                       p, src);
+  return true;
+}
+
+uint32_t 
+SerialChannel::GetNDevices (void) const
+{
+  return m_nDevices;
+}
+NetDevice *
+SerialChannel::GetDevice (uint32_t i) const
+{
+  return m_link[i].m_src->GetDevice ();
+}
+
+
+} // namespace ns3
--- a/src/devices/p2p/p2p-channel.h	Sun Mar 25 06:43:34 2007 -0700
+++ b/src/devices/p2p/p2p-channel.h	Sun Mar 25 06:59:11 2007 -0700
@@ -1,56 +1,102 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * 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
+ */
 
-// Definition of a simple point-to-point channel
-// George F. Riley, Georgia Tech, Spring 2007
+#ifndef SERIAL_CHANNEL_H
+#define SERIAL_CHANNEL_H
 
-#ifndef P2P_CHANNEL_H
-#define P2P_CHANNEL_H
-
+#include <list>
+#include "ns3/channel.h"
+#include "ns3/packet.h"
 #include "ns3/nstime.h"
-#include "ns3/mac-address.h"
 
 namespace ns3 {
 
-class P2PNetDevice;
+// temporary until Raj's code makes it into the dev tree
+typedef uint64_t DataRate;
+class SerialPhy;
 class NetDevice;
-class Node;
-class Packet;
 
-class P2PChannel  {
+/**
+ * \brief Simple Point To Point Channel.
+ *
+ * This class represents a very simple serial channel.  Think full duplex
+ * RS-232 or RS-422 with null modem and no handshaking.  There is no multi-
+ * drop capability on this channel -- there can be a maximum of two serial 
+ * net devices connected.  Once we start talking about multi-drop, or CSMA, 
+ * or some other sharing mechanism, things begin getting complicated quickly.
+ * Rather than invent some ad-hoc mechanism, we just Keep It Simple everywhere.
+ *
+ * When the channel is instaniated, the constructor takes parameters for
+ * a single channel speed, in bits per second, and a delay time as a Time
+ * object.  Both directions use the same speed and delay time.
+ *
+ * There are two "wires" in the channel.  The first device connected gets the
+ * [0] wire to transmit on.  The second device gets the [1] wire.  There is a
+ * state (IDLE, TRANSMITTING) associated with each wire.
+ */
+class SerialChannel : public Channel {
 public:
-  P2PChannel(const Time& delay, double maxRate /* bits/s */);
-  ~P2PChannel();
+//
+// This is really kidding myself, since just setting N_DEVICES to 3 isn't
+// going to come close to magically creating a multi-drop link, but I can't
+// bring myself to just type 2 in the code (even though I type 0 and 1 :-).
+//
+  static const int N_DEVICES = 2;
 
-  P2PNetDevice* CreateNetDevice(Node *node, MacAddress address);
-  void       RemoveNetDevice (NetDevice *device);
-  void       Send (P2PNetDevice *device, Packet&p, double rate /* bits/s */);
+  SerialChannel ();
+  SerialChannel (const DataRate& bps, const Time& delay);
+  SerialChannel (const std::string& name,
+                 const DataRate& bps, const Time& delay);
+
+  void Attach (SerialPhy* phy);
+  bool Propagate (Packet& p, SerialPhy *src);
+
+  virtual uint32_t GetNDevices (void) const;
+  virtual NetDevice *GetDevice (uint32_t i) const;
+
+
 private:
-  // The two endpoints of this channel
-  P2PNetDevice* m_nd1;
-  P2PNetDevice* m_nd2;
+  void TransmitCompleteEvent (Packet p, SerialPhy *src);
+
+  DataRate      m_bps;
   Time          m_delay;
-  double        m_maxRate;
+
+  int32_t       m_nDevices;
+
+  enum WireState
+    {
+      INITIALIZING,
+      IDLE,
+      TRANSMITTING
+    };
+
+  class Link
+  {
+  public:
+    Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
+    WireState        m_state;
+    SerialPhy *m_src;
+    SerialPhy *m_dst;
+  };
+    
+  Link    m_link[N_DEVICES];
 };
 
-}//namespace ns3
+} // namespace ns3
 
-#endif
+#endif /* SERIAL_CHANNEL_H */
--- a/src/devices/p2p/p2p-net-device.cc	Sun Mar 25 06:43:34 2007 -0700
+++ b/src/devices/p2p/p2p-net-device.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -1,80 +1,160 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
 
-// Implementation of a point-to-point network device
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ns3/empty-trace-resolver.h"
+#include <iostream>
+#include <cassert>
+#include "ns3/debug.h"
+#include "ns3/queue.h"
+#include "ns3/composite-trace-resolver.h"
 #include "p2p-net-device.h"
 #include "p2p-channel.h"
+#include "p2p-phy.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("SerialNetDevice");
 
 namespace ns3 {
 
-P2PNetDevice::P2PNetDevice (Node *node, MacAddress const &addr)
-  : NetDevice (node, addr),
-    m_rate (1000000)
+
+SerialNetDevice::SerialNetDevice(Node* node) : 
+  NetDevice(node, MacAddress("00:00:00:00:00:00"))
 {
-  SetMtu (2300);
+  NS_DEBUG ("SerialNetDevice::SerialNetDevice (" << node << ")");
+
+  // BUGBUG FIXME
+  //
+  // You _must_ support broadcast to get any sort of packet from the ARP layer.
   EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
+  EnableMulticast();
+  EnablePointToPoint();
+  SetMtu(512); // bytes
+
+  m_phy = new SerialPhy(node, this);
 }
 
-P2PNetDevice::~P2PNetDevice()
-{ // Inform channel that we are destroyed
-  m_channel->RemoveNetDevice(this);
+SerialNetDevice::~SerialNetDevice()
+{
+  NS_DEBUG ("SerialNetDevice::~SerialNetDevice ()");
+  delete m_phy;
 }
 
-void 
-P2PNetDevice::SetRate (double rate)
+
+bool
+SerialNetDevice::SendTo (Packet& p, const MacAddress& dest)
 {
-  m_rate = rate;
+  NS_DEBUG ("SerialNetDevice::SendTo (" << &p << ", " << &dest << ")");
+
+  assert (IsLinkUp ());
+
+#ifdef NOTYET
+    struct NetDevicePacketDestAddress tag;
+    tag.address = address;
+    p.AddTag (tag);
+#endif
+    if (m_queue->Enqueue(p) )
+      {
+        NotifyDataAvailable ();
+        return true;
+      }
+    return false;
 }
 
-void 
-P2PNetDevice::Connect (P2PChannel *channel)
+TraceResolver *
+SerialNetDevice::DoCreateTraceResolver (TraceContext const &context)
 {
-  m_channel = channel;
-  NotifyLinkUp ();
+  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
+  resolver->Add ("queue", 
+                 MakeCallback (&Queue::CreateTraceResolver, m_queue),
+                 SerialNetDevice::QUEUE);
+  resolver->Add ("rx",
+                 m_rxTrace,
+                 SerialNetDevice::RX);
+  return resolver;
 }
 
-bool 
-P2PNetDevice::SendTo (Packet& p, const MacAddress&)
+bool
+SerialNetDevice::Attach (SerialChannel* ch)
 {
-  m_channel->Send (this, p, m_rate);
+  NS_DEBUG ("SerialNetDevice::Attach (" << &ch << ")");
+
+  m_channel = ch;
+  m_phy->Attach (m_channel);
+  /* 
+   * For now, this device is up whenever a channel is attached to it.
+   * In fact, it should become up only when the second device
+   * is attached to the channel. So, there should be a way for
+   * a SerialChannel to notify both of its attached devices
+   * that the channel is 'complete', hence that the devices are
+   * up, hence that they can call NotifyLinkUp. 
+   */
+  NotifyLinkUp ();
   return true;
 }
 
-TraceResolver *
-P2PNetDevice::DoCreateTraceResolver (TraceContext const &context)
+void
+SerialNetDevice::AddQueue (Queue* q)
 {
-  return new EmptyTraceResolver (context);
+  NS_DEBUG ("SerialNetDevice::AddQueue (" << q << ")");
+
+  m_queue = q;
+}
+
+void
+SerialNetDevice::Receive (Packet& p)
+{
+  // ignore return value for now.
+  NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
+
+  m_rxTrace (p);
+  ForwardUp (p);
 }
 
 void
-P2PNetDevice::Receive(Packet p)
+SerialNetDevice::NotifyDataAvailable(void)
 {
-  ForwardUp (p);
+  NS_DEBUG ("SerialNetDevice::NotifyDataAvailable ()");
+
+  Packet p;
+  bool found = GetQueue ()->Dequeue (p);
+  if (found)
+    {
+#ifdef NOTYET
+      struct NetDevicePacketDestAddress tag;
+      p.PeekTag (tag);
+      // send packet to address tag.address
+#endif
+      NS_DEBUG ("SerialNetDevice::NotifyDataAvailable (): Dequeued");
+      m_phy->Send(p);
+    }
 }
 
-void 
-P2PNetDevice::TxComplete (void)
-{}
+Queue* 
+SerialNetDevice::GetQueue(void) const 
+{ 
+    return m_queue;
+}
 
-}//namespace ns3  
+SerialChannel* 
+SerialNetDevice::GetChannel(void) const 
+{ 
+    return m_channel;
+}
+
+} // namespace ns3
--- a/src/devices/p2p/p2p-net-device.h	Sun Mar 25 06:43:34 2007 -0700
+++ b/src/devices/p2p/p2p-net-device.h	Sun Mar 25 06:59:11 2007 -0700
@@ -1,54 +1,76 @@
-// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * 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: Craig Dowell <craigdo@ee.washington.edu>
+ */
 
-// Definition for a Point-to-Point network device
-// George F. Riley, Georgia Tech, Spring 2007
+#ifndef SERIAL_NET_DEVICE_H
+#define SERIAL_NET_DEVICE_H
 
-#ifndef P2P_NET_DEVICE_H
-#define P2P_NET_DEVICE_H
-
+#include <string.h>
+#include "ns3/mac-address.h"
+#include "ns3/node.h"
 #include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/callback-trace-source.h"
 
 namespace ns3 {
 
-class P2PChannel;
+class SerialChannel;
+class SerialPhy;
+class Queue;
 
-class P2PNetDevice : public NetDevice {
+class SerialNetDevice : public NetDevice {
 public:
-  P2PNetDevice(Node *node, MacAddress const &addr);
-  virtual ~P2PNetDevice();
+  enum TraceType {
+    QUEUE,
+    RX,
+  };
+  SerialNetDevice(Node* node);
+  virtual ~SerialNetDevice();
+
+private:
+  // Don't let the compiler slip in copy and assignment construction
+  SerialNetDevice(const SerialNetDevice&);
+  SerialNetDevice&operator=(const SerialNetDevice&);
 
-  void SetRate (double rate);
-  void Connect (P2PChannel *channel);
-  void Receive(Packet p);
-  void TxComplete (void);
- private:
+public:
+  bool Attach(SerialChannel* ch);
+  void AddQueue(Queue*);
+  // called by SerialPhy
+  void Receive (Packet& p);
+
+protected:
+  Queue* GetQueue(void) const; 
+  SerialChannel* GetChannel(void) const;
+
+private:
+  virtual void NotifyDataAvailable (void);
   virtual bool SendTo (Packet& p, const MacAddress& dest);
   virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
 
-  double m_rate;
-  P2PChannel *m_channel;
+  SerialPhy* m_phy;
+  SerialChannel* m_channel;
+  Queue* m_queue;
+  CallbackTraceSource<Packet &> m_rxTrace;
 };
 
-}//namespace ns3
+}; // namespace ns3
 
-#endif /* P2P_NET_DEVICE_H */
+#endif // SERIAL_NET_DEVICE_H
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/p2p-phy.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006 INRIA
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/debug.h"
+#include "ns3/queue.h"
+#include "p2p-phy.h"
+#include "p2p-net-device.h"
+#include "p2p-channel.h"
+
+NS_DEBUG_COMPONENT_DEFINE ("SerialPhy");
+
+namespace ns3 {
+
+SerialPhy::SerialPhy(Node* node, SerialNetDevice* netdevice) :
+  m_node(node), m_netdevice(netdevice)
+{
+  NS_DEBUG ("SerialPhy::SerialPhy (" << node << ", " << netdevice << ")");
+}
+
+SerialPhy::~SerialPhy()
+{
+  NS_DEBUG ("SerialPhy::~SerialPhy ()");
+}
+
+void 
+SerialPhy::Send (Packet &p)
+{
+  m_channel->Propagate (p, this);
+}
+void 
+SerialPhy::Attach (SerialChannel *channel)
+{
+  m_channel = channel;
+  m_channel->Attach (this);
+}
+
+SerialNetDevice *
+SerialPhy::GetDevice (void)
+{
+  return m_netdevice;
+}
+
+
+
+void
+SerialPhy::Receive (Packet& p)
+{
+  NS_DEBUG ("SerialPhy::Receive (" << &p << ")");
+  m_netdevice->Receive (p);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/p2p-phy.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * 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: Craig Dowell <craigdo@ee.washington.edu>
+ */
+
+#ifndef SERIAL_PHY_H
+#define SERIAL_PHY_H
+
+namespace ns3 {
+
+class SerialNetDevice;
+class SerialChannel;
+class Node;
+class Packet;
+
+class SerialPhy {
+public:
+  SerialPhy(Node* node, SerialNetDevice* netdevice);
+  virtual ~SerialPhy();
+
+  void Send (Packet &p);
+  void Receive (Packet& p);
+  void Attach (SerialChannel *channel);
+
+  SerialNetDevice *GetDevice (void);
+
+private:
+  Node* m_node;
+  SerialChannel *m_channel;
+  SerialNetDevice* m_netdevice;
+};
+
+} // namespace ns3
+
+#endif // SERIAL_PHY_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/p2p-topology.cc	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,171 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+
+//
+// Topology helper for ns3.
+// George F. Riley, Georgia Tech, Spring 2007
+
+#include "ns3/debug.h"
+#include "ns3/assert.h"
+
+#include "ns3/nstime.h"
+
+#include "ns3/internet-node.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/drop-tail.h"
+#include "ns3/arp-ipv4-interface.h"
+#include "ns3/ipv4.h"
+
+#include "p2p-channel.h"
+#include "p2p-net-device.h"
+#include "p2p-topology.h"
+
+#define nil 0
+
+namespace ns3 {
+
+SerialChannel *
+SerialTopology::AddSerialLink(
+  Node* a,
+  const Ipv4Address& addra,
+  Node* b,
+  const Ipv4Address& addrb,
+  uint64_t bps,
+  const Time& delay)
+{
+  SerialChannel* channel = new SerialChannel(bps, delay);
+
+  // Duplex link is assumed to be subnetted as a /30
+  // May run this unnumbered in the future?
+  Ipv4Mask netmask("255.255.255.252");
+  NS_ASSERT (netmask.IsMatch(addra,addrb));
+
+  DropTailQueue* dtqa = new DropTailQueue();
+
+  SerialNetDevice* neta = new SerialNetDevice(a);
+  neta->AddQueue(dtqa);
+  Ipv4Interface *interfA = new ArpIpv4Interface (a, neta);
+  uint32_t indexA = a->GetIpv4 ()->AddInterface (interfA);
+  neta->Attach (channel);
+
+  interfA->SetAddress (addra);
+  interfA->SetNetworkMask (netmask);
+  interfA->SetUp ();
+
+  DropTailQueue* dtqb = new DropTailQueue();
+
+  SerialNetDevice* netb = new SerialNetDevice(b);
+  netb->AddQueue(dtqb);
+  Ipv4Interface *interfB = new ArpIpv4Interface (b, netb);
+  uint32_t indexB = b->GetIpv4 ()->AddInterface (interfB);
+  netb->Attach (channel);
+
+  interfB->SetAddress (addrb);
+  interfB->SetNetworkMask (netmask);
+  interfB->SetUp ();
+
+  a->GetIpv4 ()->AddHostRouteTo (addrb, indexA);
+  b->GetIpv4 ()->AddHostRouteTo (addra, indexB);
+
+  return channel;
+}
+
+
+#if 0
+P2PChannel* Topology::AddDuplexLink(Node* n1, const IPAddr& ip1, 
+                                    Node* n2, const IPAddr& ip2,
+                                    const Rate& rate, const Time& delay)
+{
+  // First get the NetDeviceList capability from each node
+  NetDeviceList* ndl1 = n1->GetNetDeviceList();
+  NetDeviceList* ndl2 = n2->GetNetDeviceList();
+  if (!ndl1 || !ndl2) return nil;  // Both ends must have NetDeviceList
+  // Get the net devices
+  P2PNetDevice* nd1 = ndl1->Add(P2PNetDevice(n1, rate, nil));
+  P2PNetDevice* nd2 = ndl2->Add(P2PNetDevice(n1, rate, nd1->GetChannel()));
+  // Not implemented yet.  Add appropriate layer 2 protocol for
+  // the net devices.
+  // Get the L3 proto for node 1 and configure it with this device
+  L3Demux*    l3demux1 = n1->GetL3Demux();
+  L3Protocol* l3proto1 = nil;
+  // If the node 1 l3 demux exists, find the coresponding l3 protocol
+  if (l3demux1) l3proto1 = l3demux1->Lookup(ip1.L3Proto());
+  // If the l3 protocol exists, configure this net device.  Use a mask
+  // of all ones, since there is only one device on the remote end
+  // of this link
+  if (l3proto1) l3proto1->AddNetDevice(nd1, ip1, ip1.GetMask(ip1.Size()*8));
+  // Same for node 2
+  L3Demux*    l3demux2 = n2->GetL3Demux();
+  L3Protocol* l3proto2 = nil;
+  // If the node 2 l3 demux exists, find the coresponding l3 protocol
+  if (l3demux2) l3proto2 = l3demux2->Lookup(ip2.L3Proto());
+  if (l3proto2) l3proto2->AddNetDevice(nd2, ip2, ip2.GetMask(ip2.Size()*8));
+  return dynamic_cast<P2PChannel*>(nd1->GetChannel());  // Always succeeds
+}
+
+// Get the net device connecting node n1 to n2.  For topologies where
+// there are possibly multiple devices connecting n1 and n2 (for example
+// wireless with two devices on different channels) this will return
+// the first one found.
+NetDevice* Topology::GetNetDevice(Node* n1, Node* n2)
+{
+  // First get the NetDeviceList capability from node 1
+  NetDeviceList* ndl1 = n1->GetNetDeviceList();
+  if (!ndl1) return 0; // No devices, return nil
+  // Get the list of devices
+  const NetDeviceList::NetDevices_t& dlist = ndl1->GetAll();
+  for (NetDeviceList::NetDevices_t::const_iterator i = dlist.Begin();
+       i != dlist.End(); ++i)
+    { // Check each device
+      NetDevice* nd = *i; // next device
+      Channel* c = nd->GetChannel();
+      if (!c) continue; // No channel
+      if (c->NodeIsPeer(n2)) return nd; // found it
+    }
+  return 0; // None found
+}
+  
+// Get the channel connecting node n1 to node n2
+Channel* Topology::GetChannel(Node* n1, Node* n2)
+{
+  NetDevice* nd = GetNetDevice(n1, n2);
+  if (!nd) return 0; // No net device, so no channel
+  return nd->GetChannel();
+}
+
+Queue* Topology::GetQueue(Node* n1, Node* n2)
+{
+  NetDevice* nd = GetNetDevice(n1, n2);
+  if (!nd) return 0; // No net device, so in queue
+  return nd->GetQueue();
+}
+
+Queue* Topology::SetQueue(Node* n1, Node* n2, const Queue& q)
+{
+  NetDevice* nd = GetNetDevice(n1, n2);
+  if (!nd) return 0; // No net device, can't set queue
+  // Add the specified queue to the netdevice
+  return nd->SetQueue(q);
+}
+
+#endif
+
+} // namespace ns3
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/p2p-topology.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// 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: George F. Riley<riley@ece.gatech.edu>
+//
+// Topology helper for ns3.
+// George F. Riley, Georgia Tech, Spring 2007
+
+#ifndef __TOPOLOGY_H__
+#define __TOPOLOGY_H__
+
+// The topology class consists of only static methods thar are used to
+// create the topology and data flows for an ns3 simulation
+
+namespace ns3 {
+
+class SerialChannel;
+class Node;
+class IPAddr;
+//class SerialNetDevice;
+//class Queue;
+//class Rate;
+//class Time;
+  
+class SerialTopology {
+public:
+  // Manage point to point links
+
+  // Add a full-duplex point-to-point link between two nodes
+  // with the specified IP addresses,  with specified maximum transmission rate
+  // and propagation delay.
+  static SerialChannel* AddSerialLink(
+    Node*, const Ipv4Address&, 
+    Node*, const Ipv4Address&,
+    // const Rate&,
+    uint64_t,
+    const Time&);
+
+  // Get the connecting node n1 to node n2
+  static Channel* GetChannel(Node*, Node*);
+  // Get the NetDevice connecting node n1 to n2
+  static NetDevice* GetNetDevice(Node*, Node*);
+  /// Get the queue associated with a link between two nodes
+  static Queue* GetQueue(Node*, Node*);
+  // Set the queue associated with a link between two nodes
+  static Queue* SetQueue(Node*, Node*, const Queue&);
+};
+
+} // namespace ns3
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/p2p/propagator.h	Sun Mar 25 06:59:11 2007 -0700
@@ -0,0 +1,49 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007 University of Washington
+ * 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: Craig Dowell <craigdo@ee.washingon.edu>
+ *
+ *      Thu Feb 15 15:06:15 PST 2007 craigdo:  Created
+ */
+
+#ifndef PROPAGATOR_H
+#define PROPAGATOR_H
+
+#include "ns3/packet.h"
+
+namespace ns3 {
+
+class Propagator
+{
+public:
+  Propagator () : m_packet(0) {}
+  virtual ~Propagator () {}
+
+  void SetPacket (Packet &p) {DoSetPacket(p);}
+
+protected:
+  virtual void DoSetPacket (Packet &p) {m_packet = static_cast<Packet *>(&p);}
+
+  Packet *m_packet;
+private:
+};
+
+
+}; // namespace ns3
+
+#endif /* SERIAL_PHY_H */
--- a/src/devices/serial/layer-connector.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- * 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: Craig Dowell <craigdo@ee.washingon.edu>
- *
- *      Fri Feb 16 12:18:11 PST 2007 craigdo:  created
- */
-
-#include "ns3/debug.h"
-#include "ns3/assert.h"
-#include "layer-connector.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("LayerConnector");
-
-namespace ns3 {
-
-LayerConnectorUpper::LayerConnectorUpper ()
-{
-  NS_DEBUG("LayerConnectorUpper::LayerConnectorUpper ()");
-}
-
-LayerConnectorUpper::~LayerConnectorUpper ()
-{
-  NS_DEBUG("LayerConnectorUpper::~LayerConnectorUpper ()");
-}
-
-  bool
-LayerConnectorUpper::ConnectToLower (LayerConnectorLower &partner)
-{
-  NS_DEBUG("LayerConnectorUpper::ConnectToLower (" << &partner << ")");
-
-  return DoConnectToLower(partner);
-}
-
-  bool
-LayerConnectorUpper::DoConnectToLower (LayerConnectorLower &partner)
-{
-  NS_DEBUG("LayerConnectorUpper::DoConnectToLower (" << &partner << ")");
-
-  m_lowerPartner = &partner;
-  NS_ASSERT (m_lowerPartner);
-  return true;
-}
-
-  bool
-LayerConnectorUpper::UpperSendUp (Packet &p)
-{
-  NS_DEBUG("LayerConnectorUpper::UpperSendUp (" << &p << ")");
-
-  return UpperDoSendUp(p);
-}
-
-  bool
-LayerConnectorUpper::UpperPull (Packet &p)
-{
-  NS_DEBUG("LayerConnectorUpper::UpperPull (" << &p << ")");
-
-  return UpperDoPull(p);
-}
-
-  bool
-LayerConnectorUpper::UpperNotify ()
-{
-  NS_DEBUG("LayerConnectorUpper::UpperNotify ()");
-
-  NS_ASSERT (m_lowerPartner);
-  return m_lowerPartner->LowerNotify(this);
-}
-
-LayerConnectorLower::LayerConnectorLower ()
-{
-  NS_DEBUG("LayerConnectorLower::LayerConnectorLower ()");
-}
-
-LayerConnectorLower::~LayerConnectorLower ()
-{
-  NS_DEBUG("LayerConnectorLower::~LayerConnectorLower ()");
-}
-
-  bool
-LayerConnectorLower::ConnectToUpper (LayerConnectorUpper &partner)
-{
-  NS_DEBUG("LayerConnectorLower::ConnectToUpper (" << &partner << ")");
-
-  return DoConnectToUpper(partner);
-}
-
-  bool
-LayerConnectorLower::DoConnectToUpper (LayerConnectorUpper &partner)
-{
-  NS_DEBUG("LayerConnectorLower::DoConnectToUpper (" << &partner << ")");
-
-  m_upperPartner = &partner;
-  NS_ASSERT (m_upperPartner);
-  return true;
-}
-
-  bool
-LayerConnectorLower::LowerSendUp (Packet &p)
-{
-  NS_DEBUG("LayerConnectorLower::LowerSendUp (" << &p << ")");
-
-  NS_ASSERT (m_upperPartner);
-  return m_upperPartner->UpperSendUp(p);
-}
-
-  bool
-LayerConnectorLower::LowerPull (Packet &p)
-{
-  NS_DEBUG("LayerConnectorLower::LowerPull (" << &p << ")");
-
-  NS_ASSERT (m_upperPartner);
-  return m_upperPartner->UpperPull(p);
-}
-
-  bool
-LayerConnectorLower::LowerNotify (LayerConnectorUpper *upper)
-{
-  NS_DEBUG("LayerConnectorLower::LowerNotify ()");
-  return LowerDoNotify(upper);
-}
-
-} // namespace ns3
--- a/src/devices/serial/layer-connector.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- * 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: Craig Dowell <craigdo@ee.washingon.edu>
- *
- *      Wed Feb 14 16:05:46 PST 2007 craigdo:  created
- */
-
-#include "ns3/packet.h"
-
-#ifndef LAYER_CONNECTOR_H
-#define LAYER_CONNECTOR_H
-
-namespace ns3 {
-
-class LayerConnectorLower;
-
-class LayerConnectorUpper {
-public:
-  LayerConnectorUpper ();
-  virtual ~LayerConnectorUpper ();
-
-  // called by the layer connector to introduce the lower interface to us here
-  bool ConnectToLower (LayerConnectorLower &lower);
-
-  // called by the lower layer to send a received packet on up the protocol
-  // stack to us here.
-  bool UpperSendUp (Packet &p);
-
-  // Call this function to tell a lower layer that there is data available
-  // here.  It is expected that the lower layer will call pull as soon as
-  // possible to get the data.
-  bool UpperNotify ();
-
-  // called by the lower layer to get available packet data that was implied
-  // by a previous Notify() call.
-  bool UpperPull(Packet &p);
-
-protected:
-  virtual bool DoConnectToLower (LayerConnectorLower &lower);
-  virtual bool UpperDoSendUp (Packet &p) = 0;
-  virtual bool UpperDoPull (Packet &p) = 0;
-
-  LayerConnectorLower *m_lowerPartner;
-
-private:
-};
-
-class LayerConnectorLower
-{
-public:
-  LayerConnectorLower ();
-  virtual ~LayerConnectorLower ();
-
-  // This function is called by the layer connector to introduce the upper
-  // layer interface to us here
-  bool ConnectToUpper (LayerConnectorUpper &upper);
-
-  // Notify is called by the upper layer connector to tell us that there
-  // is data available.  It is expected that we will call pull (below) as
-  // soon as possible to get the data.
-  bool LowerNotify (LayerConnectorUpper *upper);
-
-  // The lower connector calls this method to send a received packet on up 
-  // the protocol stack
-  bool LowerSendUp (Packet &p);
-
-  // Call this function to get available packet data from the upper connector
-  // that was implied by a previous Notify() call.
-  bool LowerPull(Packet &p);
-
-protected:
-  virtual bool DoConnectToUpper (LayerConnectorUpper &upper);
-  virtual bool LowerDoNotify (LayerConnectorUpper *upper) = 0;
-  LayerConnectorUpper *m_upperPartner;
-
-private:
-};
-
-}; // namespace ns3
-
-#endif /* LAYER_CONNECTOR_H */
--- a/src/devices/serial/propagator.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- * 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: Craig Dowell <craigdo@ee.washingon.edu>
- *
- *      Thu Feb 15 15:06:15 PST 2007 craigdo:  Created
- */
-
-#ifndef PROPAGATOR_H
-#define PROPAGATOR_H
-
-#include "ns3/packet.h"
-
-namespace ns3 {
-
-class Propagator
-{
-public:
-  Propagator () : m_packet(0) {}
-  virtual ~Propagator () {}
-
-  void SetPacket (Packet &p) {DoSetPacket(p);}
-
-protected:
-  virtual void DoSetPacket (Packet &p) {m_packet = static_cast<Packet *>(&p);}
-
-  Packet *m_packet;
-private:
-};
-
-
-}; // namespace ns3
-
-#endif /* SERIAL_PHY_H */
--- a/src/devices/serial/serial-channel.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- * 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: Craig Dowell <craigdo@ee.washington.edu>
- */
-
-#include "serial-channel.h"
-#include "serial-net-device.h"
-#include "serial-phy.h"
-#include "ns3/packet.h"
-#include "ns3/simulator.h"
-#include "ns3/debug.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("SerialChannel");
-
-namespace ns3 {
-
-//
-// By default, you get a channel with the name "Serial Channel" that has an
-// "infitely" fast transmission speed and zero delay.
-// XXX: this does not work because m_bps = 0 results in infinitely slow transmission
-// speed. 
-SerialChannel::SerialChannel()
-: 
-  Channel ("Serial Channel"), 
-  m_bps (0),
-  m_delay (Seconds(0)),
-  m_nDevices(0)
-{
-  NS_DEBUG("SerialChannel::SerialChannel ()");
-}
-
-SerialChannel::SerialChannel(
-  const DataRate& bps, 
-  const Time& delay)
-: 
-  Channel ("Serial Channel"), 
-  m_bps (bps), 
-  m_delay (delay),
-  m_nDevices(0)
-{
-  NS_DEBUG("SerialChannel::SerialChannel (" << Channel::GetName() << ", " << bps << ", " << 
-    delay << ")");
-}
-
-SerialChannel::SerialChannel(
-  const std::string& name,
-  const DataRate& bps, 
-  const Time& delay)
-: 
-  Channel (name),
-  m_bps (bps), 
-  m_delay (delay),
-  m_nDevices(0)
-{
-  NS_DEBUG("SerialChannel::SerialChannel (" << name << ", " << bps << ", " << 
-    delay << ")");
-}
-
-  void
-SerialChannel::Attach(SerialPhy *phy)
-{
-  NS_DEBUG("SerialChannel::Attach (" << phy << ")");
-  NS_ASSERT(m_nDevices < N_DEVICES && "Only two devices permitted");
-  NS_ASSERT(phy);
-
-  m_link[m_nDevices].m_src = phy;
-  ++m_nDevices;
-//
-// If we have both devices connected to the channel, then finish introducing
-// the two halves and set the links to IDLE.
-//
-  if (m_nDevices == N_DEVICES)
-    {
-      m_link[0].m_dst = m_link[1].m_src;
-      m_link[1].m_dst = m_link[0].m_src;
-      m_link[0].m_state = IDLE;
-      m_link[1].m_state = IDLE;
-    }
-}
-
-void
-SerialChannel::TransmitCompleteEvent(Packet p, SerialPhy *src)
-{
-  NS_DEBUG("SerialChannel::TransmitCompleteEvent (" << &p << ", " << 
-    src << ")");
-
-  NS_ASSERT(m_link[0].m_state != INITIALIZING);
-  NS_ASSERT(m_link[1].m_state != INITIALIZING);
-  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
-  NS_ASSERT(m_link[wire].m_state == TRANSMITTING);
-
-  m_link[wire].m_state = IDLE;
-  
-  NS_DEBUG("SerialChannel::TransmitCompleteEvent (): Receive()");
-
-  m_link[wire].m_dst->Receive (p);
-}
-
-bool
-SerialChannel::Propagate(Packet& p, SerialPhy* src)
-{
-  NS_DEBUG("SerialChannel::DoPropagate (" << &p << ", " << src << ")");
-
-  NS_ASSERT(m_link[0].m_state != INITIALIZING);
-  NS_ASSERT(m_link[1].m_state != INITIALIZING);
-
-  uint32_t wire = src == m_link[0].m_src ? 0 : 1;
-
-  if (m_link[wire].m_state == TRANSMITTING)
-    {
-      NS_DEBUG("SerialChannel::DoPropagate (): TRANSMITTING, return");
-      return false;
-    }
-
-  m_link[wire].m_state = TRANSMITTING;
-
-//
-// I believe Raj has a method in the DataRate class to do this.  Should use
-// it when it is available.
-//
-  Time tEvent =  Seconds (static_cast<double> (p.GetSize() * 8) / 
-                          static_cast<double> (m_bps)) + m_delay;
-
-  NS_DEBUG("SerialChannel::DoSend (): Schedule Receive delay " << tEvent);
-
-  Packet packet = p;
-  Simulator::Schedule (tEvent, &SerialChannel::TransmitCompleteEvent, this, 
-                       p, src);
-  return true;
-}
-
-uint32_t 
-SerialChannel::GetNDevices (void) const
-{
-  return m_nDevices;
-}
-NetDevice *
-SerialChannel::GetDevice (uint32_t i) const
-{
-  return m_link[i].m_src->GetDevice ();
-}
-
-
-} // namespace ns3
--- a/src/devices/serial/serial-channel.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef SERIAL_CHANNEL_H
-#define SERIAL_CHANNEL_H
-
-#include <list>
-#include "ns3/channel.h"
-#include "ns3/packet.h"
-#include "ns3/nstime.h"
-
-namespace ns3 {
-
-// temporary until Raj's code makes it into the dev tree
-typedef uint64_t DataRate;
-class SerialPhy;
-class NetDevice;
-
-/**
- * \brief Simple Serial Channel.
- *
- * This class represents a very simple serial channel.  Think full duplex
- * RS-232 or RS-422 with null modem and no handshaking.  There is no multi-
- * drop capability on this channel -- there can be a maximum of two serial 
- * net devices connected.  Once we start talking about multi-drop, or CSMA, 
- * or some other sharing mechanism, things begin getting complicated quickly.
- * Rather than invent some ad-hoc mechanism, we just Keep It Simple everywhere.
- *
- * When the channel is instaniated, the constructor takes parameters for
- * a single channel speed, in bits per second, and a delay time as a Time
- * object.  Both directions use the same speed and delay time.
- *
- * There are two "wires" in the channel.  The first device connected gets the
- * [0] wire to transmit on.  The second device gets the [1] wire.  There is a
- * state (IDLE, TRANSMITTING) associated with each wire.
- */
-class SerialChannel : public Channel {
-public:
-//
-// This is really kidding myself, since just setting N_DEVICES to 3 isn't
-// going to come close to magically creating a multi-drop link, but I can't
-// bring myself to just type 2 in the code (even though I type 0 and 1 :-).
-//
-  static const int N_DEVICES = 2;
-
-  SerialChannel ();
-  SerialChannel (const DataRate& bps, const Time& delay);
-  SerialChannel (const std::string& name,
-                 const DataRate& bps, const Time& delay);
-
-  void Attach (SerialPhy* phy);
-  bool Propagate (Packet& p, SerialPhy *src);
-
-  virtual uint32_t GetNDevices (void) const;
-  virtual NetDevice *GetDevice (uint32_t i) const;
-
-
-private:
-  void TransmitCompleteEvent (Packet p, SerialPhy *src);
-
-  DataRate      m_bps;
-  Time          m_delay;
-
-  int32_t       m_nDevices;
-
-  enum WireState
-    {
-      INITIALIZING,
-      IDLE,
-      TRANSMITTING
-    };
-
-  class Link
-  {
-  public:
-    Link() : m_state (INITIALIZING), m_src (0), m_dst (0) {}
-    WireState        m_state;
-    SerialPhy *m_src;
-    SerialPhy *m_dst;
-  };
-    
-  Link    m_link[N_DEVICES];
-};
-
-} // namespace ns3
-
-#endif /* SERIAL_CHANNEL_H */
--- a/src/devices/serial/serial-net-device.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include <iostream>
-#include <cassert>
-#include "ns3/debug.h"
-#include "ns3/queue.h"
-#include "ns3/composite-trace-resolver.h"
-#include "serial-net-device.h"
-#include "serial-channel.h"
-#include "serial-phy.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("SerialNetDevice");
-
-namespace ns3 {
-
-
-SerialNetDevice::SerialNetDevice(Node* node) : 
-  NetDevice(node, MacAddress("00:00:00:00:00:00"))
-{
-  NS_DEBUG ("SerialNetDevice::SerialNetDevice (" << node << ")");
-
-  // BUGBUG FIXME
-  //
-  // You _must_ support broadcast to get any sort of packet from the ARP layer.
-  EnableBroadcast (MacAddress ("ff:ff:ff:ff:ff:ff"));
-  EnableMulticast();
-  EnablePointToPoint();
-  SetMtu(512); // bytes
-
-  m_phy = new SerialPhy(node, this);
-}
-
-SerialNetDevice::~SerialNetDevice()
-{
-  NS_DEBUG ("SerialNetDevice::~SerialNetDevice ()");
-  delete m_phy;
-}
-
-
-bool
-SerialNetDevice::SendTo (Packet& p, const MacAddress& dest)
-{
-  NS_DEBUG ("SerialNetDevice::SendTo (" << &p << ", " << &dest << ")");
-
-  assert (IsLinkUp ());
-
-#ifdef NOTYET
-    struct NetDevicePacketDestAddress tag;
-    tag.address = address;
-    p.AddTag (tag);
-#endif
-    if (m_queue->Enqueue(p) )
-      {
-        NotifyDataAvailable ();
-        return true;
-      }
-    return false;
-}
-
-TraceResolver *
-SerialNetDevice::DoCreateTraceResolver (TraceContext const &context)
-{
-  CompositeTraceResolver *resolver = new CompositeTraceResolver (context);
-  resolver->Add ("queue", 
-                 MakeCallback (&Queue::CreateTraceResolver, m_queue),
-                 SerialNetDevice::QUEUE);
-  resolver->Add ("rx",
-                 m_rxTrace,
-                 SerialNetDevice::RX);
-  return resolver;
-}
-
-bool
-SerialNetDevice::Attach (SerialChannel* ch)
-{
-  NS_DEBUG ("SerialNetDevice::Attach (" << &ch << ")");
-
-  m_channel = ch;
-  m_phy->Attach (m_channel);
-  /* 
-   * For now, this device is up whenever a channel is attached to it.
-   * In fact, it should become up only when the second device
-   * is attached to the channel. So, there should be a way for
-   * a SerialChannel to notify both of its attached devices
-   * that the channel is 'complete', hence that the devices are
-   * up, hence that they can call NotifyLinkUp. 
-   */
-  NotifyLinkUp ();
-  return true;
-}
-
-void
-SerialNetDevice::AddQueue (Queue* q)
-{
-  NS_DEBUG ("SerialNetDevice::AddQueue (" << q << ")");
-
-  m_queue = q;
-}
-
-void
-SerialNetDevice::Receive (Packet& p)
-{
-  // ignore return value for now.
-  NS_DEBUG ("SerialNetDevice::Receive (" << &p << ")");
-
-  m_rxTrace (p);
-  ForwardUp (p);
-}
-
-void
-SerialNetDevice::NotifyDataAvailable(void)
-{
-  NS_DEBUG ("SerialNetDevice::NotifyDataAvailable ()");
-
-  Packet p;
-  bool found = GetQueue ()->Dequeue (p);
-  if (found)
-    {
-#ifdef NOTYET
-      struct NetDevicePacketDestAddress tag;
-      p.PeekTag (tag);
-      // send packet to address tag.address
-#endif
-      NS_DEBUG ("SerialNetDevice::NotifyDataAvailable (): Dequeued");
-      m_phy->Send(p);
-    }
-}
-
-Queue* 
-SerialNetDevice::GetQueue(void) const 
-{ 
-    return m_queue;
-}
-
-SerialChannel* 
-SerialNetDevice::GetChannel(void) const 
-{ 
-    return m_channel;
-}
-
-} // namespace ns3
--- a/src/devices/serial/serial-net-device.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * 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: Craig Dowell <craigdo@ee.washington.edu>
- */
-
-#ifndef SERIAL_NET_DEVICE_H
-#define SERIAL_NET_DEVICE_H
-
-#include <string.h>
-#include "ns3/mac-address.h"
-#include "ns3/node.h"
-#include "ns3/net-device.h"
-#include "ns3/callback.h"
-#include "ns3/packet.h"
-#include "ns3/callback-trace-source.h"
-
-namespace ns3 {
-
-class SerialChannel;
-class SerialPhy;
-class Queue;
-
-class SerialNetDevice : public NetDevice {
-public:
-  enum TraceType {
-    QUEUE,
-    RX,
-  };
-  SerialNetDevice(Node* node);
-  virtual ~SerialNetDevice();
-
-private:
-  // Don't let the compiler slip in copy and assignment construction
-  SerialNetDevice(const SerialNetDevice&);
-  SerialNetDevice&operator=(const SerialNetDevice&);
-
-public:
-  bool Attach(SerialChannel* ch);
-  void AddQueue(Queue*);
-  // called by SerialPhy
-  void Receive (Packet& p);
-
-protected:
-  Queue* GetQueue(void) const; 
-  SerialChannel* GetChannel(void) const;
-
-private:
-  virtual void NotifyDataAvailable (void);
-  virtual bool SendTo (Packet& p, const MacAddress& dest);
-  virtual TraceResolver *DoCreateTraceResolver (TraceContext const &context);
-
-  SerialPhy* m_phy;
-  SerialChannel* m_channel;
-  Queue* m_queue;
-  CallbackTraceSource<Packet &> m_rxTrace;
-};
-
-}; // namespace ns3
-
-#endif // SERIAL_NET_DEVICE_H
-
--- a/src/devices/serial/serial-phy.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2005,2006 INRIA
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
- */
-
-#include "ns3/debug.h"
-#include "ns3/queue.h"
-#include "serial-phy.h"
-#include "serial-net-device.h"
-#include "serial-channel.h"
-
-NS_DEBUG_COMPONENT_DEFINE ("SerialPhy");
-
-namespace ns3 {
-
-SerialPhy::SerialPhy(Node* node, SerialNetDevice* netdevice) :
-  m_node(node), m_netdevice(netdevice)
-{
-  NS_DEBUG ("SerialPhy::SerialPhy (" << node << ", " << netdevice << ")");
-}
-
-SerialPhy::~SerialPhy()
-{
-  NS_DEBUG ("SerialPhy::~SerialPhy ()");
-}
-
-void 
-SerialPhy::Send (Packet &p)
-{
-  m_channel->Propagate (p, this);
-}
-void 
-SerialPhy::Attach (SerialChannel *channel)
-{
-  m_channel = channel;
-  m_channel->Attach (this);
-}
-
-SerialNetDevice *
-SerialPhy::GetDevice (void)
-{
-  return m_netdevice;
-}
-
-
-
-void
-SerialPhy::Receive (Packet& p)
-{
-  NS_DEBUG ("SerialPhy::Receive (" << &p << ")");
-  m_netdevice->Receive (p);
-}
-
-} // namespace ns3
--- a/src/devices/serial/serial-phy.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,50 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2007 University of Washington
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * 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: Craig Dowell <craigdo@ee.washington.edu>
- */
-
-#ifndef SERIAL_PHY_H
-#define SERIAL_PHY_H
-
-namespace ns3 {
-
-class SerialNetDevice;
-class SerialChannel;
-class Node;
-class Packet;
-
-class SerialPhy {
-public:
-  SerialPhy(Node* node, SerialNetDevice* netdevice);
-  virtual ~SerialPhy();
-
-  void Send (Packet &p);
-  void Receive (Packet& p);
-  void Attach (SerialChannel *channel);
-
-  SerialNetDevice *GetDevice (void);
-
-private:
-  Node* m_node;
-  SerialChannel *m_channel;
-  SerialNetDevice* m_netdevice;
-};
-
-} // namespace ns3
-
-#endif // SERIAL_PHY_H
--- a/src/devices/serial/serial-topology.cc	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-
-//
-// Topology helper for ns3.
-// George F. Riley, Georgia Tech, Spring 2007
-
-#include "ns3/debug.h"
-#include "ns3/assert.h"
-
-#include "ns3/nstime.h"
-
-#include "ns3/internet-node.h"
-#include "ns3/ipv4-address.h"
-#include "ns3/drop-tail.h"
-#include "ns3/arp-ipv4-interface.h"
-#include "ns3/ipv4.h"
-
-#include "serial-channel.h"
-#include "serial-net-device.h"
-#include "serial-topology.h"
-
-#define nil 0
-
-namespace ns3 {
-
-SerialChannel *
-SerialTopology::AddSerialLink(
-  Node* a,
-  const Ipv4Address& addra,
-  Node* b,
-  const Ipv4Address& addrb,
-  uint64_t bps,
-  const Time& delay)
-{
-  SerialChannel* channel = new SerialChannel(bps, delay);
-
-  // Duplex link is assumed to be subnetted as a /30
-  // May run this unnumbered in the future?
-  Ipv4Mask netmask("255.255.255.252");
-  NS_ASSERT (netmask.IsMatch(addra,addrb));
-
-  DropTailQueue* dtqa = new DropTailQueue();
-
-  SerialNetDevice* neta = new SerialNetDevice(a);
-  neta->AddQueue(dtqa);
-  Ipv4Interface *interfA = new ArpIpv4Interface (a, neta);
-  uint32_t indexA = a->GetIpv4 ()->AddInterface (interfA);
-  neta->Attach (channel);
-
-  interfA->SetAddress (addra);
-  interfA->SetNetworkMask (netmask);
-  interfA->SetUp ();
-
-  DropTailQueue* dtqb = new DropTailQueue();
-
-  SerialNetDevice* netb = new SerialNetDevice(b);
-  netb->AddQueue(dtqb);
-  Ipv4Interface *interfB = new ArpIpv4Interface (b, netb);
-  uint32_t indexB = b->GetIpv4 ()->AddInterface (interfB);
-  netb->Attach (channel);
-
-  interfB->SetAddress (addrb);
-  interfB->SetNetworkMask (netmask);
-  interfB->SetUp ();
-
-  a->GetIpv4 ()->AddHostRouteTo (addrb, indexA);
-  b->GetIpv4 ()->AddHostRouteTo (addra, indexB);
-
-  return channel;
-}
-
-
-#if 0
-P2PChannel* Topology::AddDuplexLink(Node* n1, const IPAddr& ip1, 
-                                    Node* n2, const IPAddr& ip2,
-                                    const Rate& rate, const Time& delay)
-{
-  // First get the NetDeviceList capability from each node
-  NetDeviceList* ndl1 = n1->GetNetDeviceList();
-  NetDeviceList* ndl2 = n2->GetNetDeviceList();
-  if (!ndl1 || !ndl2) return nil;  // Both ends must have NetDeviceList
-  // Get the net devices
-  P2PNetDevice* nd1 = ndl1->Add(P2PNetDevice(n1, rate, nil));
-  P2PNetDevice* nd2 = ndl2->Add(P2PNetDevice(n1, rate, nd1->GetChannel()));
-  // Not implemented yet.  Add appropriate layer 2 protocol for
-  // the net devices.
-  // Get the L3 proto for node 1 and configure it with this device
-  L3Demux*    l3demux1 = n1->GetL3Demux();
-  L3Protocol* l3proto1 = nil;
-  // If the node 1 l3 demux exists, find the coresponding l3 protocol
-  if (l3demux1) l3proto1 = l3demux1->Lookup(ip1.L3Proto());
-  // If the l3 protocol exists, configure this net device.  Use a mask
-  // of all ones, since there is only one device on the remote end
-  // of this link
-  if (l3proto1) l3proto1->AddNetDevice(nd1, ip1, ip1.GetMask(ip1.Size()*8));
-  // Same for node 2
-  L3Demux*    l3demux2 = n2->GetL3Demux();
-  L3Protocol* l3proto2 = nil;
-  // If the node 2 l3 demux exists, find the coresponding l3 protocol
-  if (l3demux2) l3proto2 = l3demux2->Lookup(ip2.L3Proto());
-  if (l3proto2) l3proto2->AddNetDevice(nd2, ip2, ip2.GetMask(ip2.Size()*8));
-  return dynamic_cast<P2PChannel*>(nd1->GetChannel());  // Always succeeds
-}
-
-// Get the net device connecting node n1 to n2.  For topologies where
-// there are possibly multiple devices connecting n1 and n2 (for example
-// wireless with two devices on different channels) this will return
-// the first one found.
-NetDevice* Topology::GetNetDevice(Node* n1, Node* n2)
-{
-  // First get the NetDeviceList capability from node 1
-  NetDeviceList* ndl1 = n1->GetNetDeviceList();
-  if (!ndl1) return 0; // No devices, return nil
-  // Get the list of devices
-  const NetDeviceList::NetDevices_t& dlist = ndl1->GetAll();
-  for (NetDeviceList::NetDevices_t::const_iterator i = dlist.Begin();
-       i != dlist.End(); ++i)
-    { // Check each device
-      NetDevice* nd = *i; // next device
-      Channel* c = nd->GetChannel();
-      if (!c) continue; // No channel
-      if (c->NodeIsPeer(n2)) return nd; // found it
-    }
-  return 0; // None found
-}
-  
-// Get the channel connecting node n1 to node n2
-Channel* Topology::GetChannel(Node* n1, Node* n2)
-{
-  NetDevice* nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so no channel
-  return nd->GetChannel();
-}
-
-Queue* Topology::GetQueue(Node* n1, Node* n2)
-{
-  NetDevice* nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, so in queue
-  return nd->GetQueue();
-}
-
-Queue* Topology::SetQueue(Node* n1, Node* n2, const Queue& q)
-{
-  NetDevice* nd = GetNetDevice(n1, n2);
-  if (!nd) return 0; // No net device, can't set queue
-  // Add the specified queue to the netdevice
-  return nd->SetQueue(q);
-}
-
-#endif
-
-} // namespace ns3
- 
--- a/src/devices/serial/serial-topology.h	Sun Mar 25 06:43:34 2007 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-//
-// Copyright (c) 2006 Georgia Tech Research Corporation
-//
-// 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: George F. Riley<riley@ece.gatech.edu>
-//
-// Topology helper for ns3.
-// George F. Riley, Georgia Tech, Spring 2007
-
-#ifndef __TOPOLOGY_H__
-#define __TOPOLOGY_H__
-
-// The topology class consists of only static methods thar are used to
-// create the topology and data flows for an ns3 simulation
-
-namespace ns3 {
-
-class SerialChannel;
-class Node;
-class IPAddr;
-//class SerialNetDevice;
-//class Queue;
-//class Rate;
-//class Time;
-  
-class SerialTopology {
-public:
-  // Manage point to point links
-
-  // Add a full-duplex point-to-point serial link between two nodes
-  // with the specified IP addresses,  with specified maximum transmission rate
-  // and propagation delay.
-  static SerialChannel* AddSerialLink(
-    Node*, const Ipv4Address&, 
-    Node*, const Ipv4Address&,
-    // const Rate&,
-    uint64_t,
-    const Time&);
-
-  // Get the connecting node n1 to node n2
-  static Channel* GetChannel(Node*, Node*);
-  // Get the NetDevice connecting node n1 to n2
-  static NetDevice* GetNetDevice(Node*, Node*);
-  /// Get the queue associated with a link between two nodes
-  static Queue* GetQueue(Node*, Node*);
-  // Set the queue associated with a link between two nodes
-  static Queue* SetQueue(Node*, Node*, const Queue&);
-};
-
-} // namespace ns3
-
-#endif
-