commit 13e4bf1aa79d43e954e642095025e91bee656ad1
Author: Tim Schubert <tim.schubert@tu-bs.de>
Date:   Sat Jun 20 16:14:00 2020 +0200

    init

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1377554
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/doc/leo.rst b/doc/leo.rst
new file mode 100644
index 0000000..3dcd9d2
--- /dev/null
+++ b/doc/leo.rst
@@ -0,0 +1,98 @@
+Example Module Documentation
+----------------------------
+
+.. include:: replace.txt
+.. highlight:: cpp
+
+.. heading hierarchy:
+   ------------- Chapter
+   ************* Section (#.#)
+   ============= Subsection (#.#.#)
+   ############# Paragraph (no number)
+
+This is a suggested outline for adding new module documentation to |ns3|.
+See ``src/click/doc/click.rst`` for an example.
+
+The introductory paragraph is for describing what this code is trying to
+model.
+
+For consistency (italicized formatting), please use |ns3| to refer to
+ns-3 in the documentation (and likewise, |ns2| for ns-2).  These macros
+are defined in the file ``replace.txt``.
+
+Model Description
+*****************
+
+The source code for the new module lives in the directory ``src/leo``.
+
+Add here a basic description of what is being modeled.
+
+Design
+======
+
+Briefly describe the software design of the model and how it fits into 
+the existing ns-3 architecture. 
+
+Scope and Limitations
+=====================
+
+What can the model do?  What can it not do?  Please use this section to
+describe the scope and limitations of the model.
+
+References
+==========
+
+Add academic citations here, such as if you published a paper on this
+model, or if readers should read a particular specification or other work.
+
+Usage
+*****
+
+This section is principally concerned with the usage of your model, using
+the public API.  Focus first on most common usage patterns, then go
+into more advanced topics.
+
+Building New Module
+===================
+
+Include this subsection only if there are special build instructions or
+platform limitations.
+
+Helpers
+=======
+
+What helper API will users typically use?  Describe it here.
+
+Attributes
+==========
+
+What classes hold attributes, and what are the key ones worth mentioning?
+
+Output
+======
+
+What kind of data does the model generate?  What are the key trace
+sources?   What kind of logging output can be enabled?
+
+Advanced Usage
+==============
+
+Go into further details (such as using the API outside of the helpers)
+in additional sections, as needed.
+
+Examples
+========
+
+What examples using this new code are available?  Describe them here.
+
+Troubleshooting
+===============
+
+Add any tips for avoiding pitfalls, etc.
+
+Validation
+**********
+
+Describe how the model has been tested/validated.  What tests run in the
+test suite?  How much API and code is covered by the tests?  Again, 
+references to outside published work may help here.
diff --git a/examples/isl-example.cc b/examples/isl-example.cc
new file mode 100644
index 0000000..76f70f9
--- /dev/null
+++ b/examples/isl-example.cc
@@ -0,0 +1,66 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/node-container.h"
+
+#include "ns3/leo-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("IslExample");
+
+int
+main (int argc, char *argv[])
+{
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
+  Time::SetResolution (Time::NS);
+  LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
+  LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
+  LogComponentEnable ("UdpClient", LOG_LEVEL_DEBUG);
+  LogComponentEnable ("IslChannel", LOG_LEVEL_LOGIC);
+
+  NodeContainer nodes;
+  nodes.Create (2);
+
+  IslHelper isl;
+  isl.SetDeviceAttribute ("DataRate", StringValue ("5Gbps"));
+  isl.SetChannelAttribute ("PropagationDelay", StringValue ("ns3::ConstantSpeedPropagationDelayModel"));
+  isl.SetChannelAttribute ("PropagationLoss", StringValue ("ns3::IslPropagationLossModel"));
+  isl.SetDeviceAttribute ("MobilityModel", StringValue ("ns3::LeoMobilityModel"));
+
+  NetDeviceContainer devices;
+  devices = isl.Install (nodes);
+
+  InternetStackHelper stack;
+  stack.Install (nodes);
+
+  Ipv6AddressHelper address;
+
+  Ipv6InterfaceContainer interfaces = address.Assign (devices);
+
+  UdpEchoServerHelper echoServer (9);
+
+  ApplicationContainer serverApps = echoServer.Install (nodes.Get (1));
+  serverApps.Start (Seconds (1.0));
+  serverApps.Stop (Seconds (10.0));
+
+  Address destAddress = interfaces.GetAddress (1, 0);
+  UdpEchoClientHelper echoClient (destAddress, 9);
+  echoClient.SetAttribute ("MaxPackets", UintegerValue (10));
+  echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
+  echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
+
+  ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
+  clientApps.Start (Seconds (2.0));
+  clientApps.Stop (Seconds (10.0));
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return 0;
+}
diff --git a/examples/leo-example.cc b/examples/leo-example.cc
new file mode 100644
index 0000000..da74093
--- /dev/null
+++ b/examples/leo-example.cc
@@ -0,0 +1,26 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "ns3/core-module.h"
+#include "ns3/leo-helper.h"
+
+using namespace ns3;
+
+
+int 
+main (int argc, char *argv[])
+{
+  bool verbose = true;
+
+  CommandLine cmd;
+  cmd.AddValue ("verbose", "Tell application to log if true", verbose);
+
+  cmd.Parse (argc,argv);
+
+  /* ... */
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+  return 0;
+}
+
+
diff --git a/examples/wscript b/examples/wscript
new file mode 100644
index 0000000..ed4a77c
--- /dev/null
+++ b/examples/wscript
@@ -0,0 +1,9 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('leo-example', ['leo'])
+    obj.source = 'leo-example.cc'
+
+    obj = bld.create_ns3_program('isl-example', ['leo'])
+    obj.source = 'isl-example.cc'
+
diff --git a/helper/isl-helper.cc b/helper/isl-helper.cc
new file mode 100644
index 0000000..3af9480
--- /dev/null
+++ b/helper/isl-helper.cc
@@ -0,0 +1,258 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+
+#include "ns3/abort.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-remote-channel.h"
+#include "ns3/queue.h"
+#include "ns3/config.h"
+#include "ns3/packet.h"
+#include "ns3/names.h"
+#include "ns3/trace-helper.h"
+
+#include "../model/isl-net-device.h"
+#include "../model/isl-channel.h"
+#include "isl-helper.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("IslHelper");
+
+IslHelper::IslHelper ()
+{
+  m_queueFactory.SetTypeId ("ns3::DropTailQueue<Packet>");
+  m_deviceFactory.SetTypeId ("ns3::IslNetDevice");
+  m_channelFactory.SetTypeId ("ns3::IslChannel");
+}
+
+void
+IslHelper::SetQueue (std::string type,
+                              std::string n1, const AttributeValue &v1,
+                              std::string n2, const AttributeValue &v2,
+                              std::string n3, const AttributeValue &v3,
+                              std::string n4, const AttributeValue &v4)
+{
+  QueueBase::AppendItemTypeIfNotPresent (type, "Packet");
+
+  m_queueFactory.SetTypeId (type);
+  m_queueFactory.Set (n1, v1);
+  m_queueFactory.Set (n2, v2);
+  m_queueFactory.Set (n3, v3);
+  m_queueFactory.Set (n4, v4);
+}
+
+void
+IslHelper::SetDeviceAttribute (std::string n1, const AttributeValue &v1)
+{
+  m_deviceFactory.Set (n1, v1);
+}
+
+void
+IslHelper::SetChannelAttribute (std::string n1, const AttributeValue &v1)
+{
+  m_channelFactory.Set (n1, v1);
+}
+
+void
+IslHelper::EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename)
+{
+  //
+  // All of the Pcap enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type IslNetDevice.
+  //
+  Ptr<IslNetDevice> device = nd->GetObject<IslNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("IslHelper::EnablePcapInternal(): Device " << device << " not of type ns3::IslNetDevice");
+      return;
+    }
+
+  PcapHelper pcapHelper;
+
+  std::string filename;
+  if (explicitFilename)
+    {
+      filename = prefix;
+    }
+  else
+    {
+      filename = pcapHelper.GetFilenameFromDevice (prefix, device);
+    }
+
+  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out,
+                                                     PcapHelper::DLT_PPP);
+  pcapHelper.HookDefaultSink<IslNetDevice> (device, "PromiscSniffer", file);
+}
+
+void
+IslHelper::EnableAsciiInternal (
+  Ptr<OutputStreamWrapper> stream,
+  std::string prefix,
+  Ptr<NetDevice> nd,
+  bool explicitFilename)
+{
+  //
+  // All of the ascii enable functions vector through here including the ones
+  // that are wandering through all of devices on perhaps all of the nodes in
+  // the system.  We can only deal with devices of type IslNetDevice.
+  //
+  Ptr<IslNetDevice> device = nd->GetObject<IslNetDevice> ();
+  if (device == 0)
+    {
+      NS_LOG_INFO ("IslHelper::EnableAsciiInternal(): Device " << device <<
+                   " not of type ns3::IslNetDevice");
+      return;
+    }
+
+  //
+  // Our default trace sinks are going to use packet printing, so we have to
+  // make sure that is turned on.
+  //
+  Packet::EnablePrinting ();
+
+  //
+  // If we are not provided an OutputStreamWrapper, we are expected to create
+  // one using the usual trace filename conventions and do a Hook*WithoutContext
+  // since there will be one file per context and therefore the context would
+  // be redundant.
+  //
+  if (stream == 0)
+    {
+      //
+      // Set up an output stream object to deal with private ofstream copy
+      // constructor and lifetime issues.  Let the helper decide the actual
+      // name of the file given the prefix.
+      //
+      AsciiTraceHelper asciiTraceHelper;
+
+      std::string filename;
+      if (explicitFilename)
+        {
+          filename = prefix;
+        }
+      else
+        {
+          filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device);
+        }
+
+      Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
+
+      //
+      // The MacRx trace source provides our "r" event.
+      //
+      asciiTraceHelper.HookDefaultReceiveSinkWithoutContext<IslNetDevice> (device, "MacRx", theStream);
+
+      //
+      // The "+", '-', and 'd' events are driven by trace sources actually in the
+      // transmit queue.
+      //
+      Ptr<Queue<Packet> > queue = device->GetQueue ();
+      asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext<Queue<Packet> > (queue, "Enqueue", theStream);
+      asciiTraceHelper.HookDefaultDropSinkWithoutContext<Queue<Packet> > (queue, "Drop", theStream);
+      asciiTraceHelper.HookDefaultDequeueSinkWithoutContext<Queue<Packet> > (queue, "Dequeue", theStream);
+
+      // PhyRxDrop trace source for "d" event
+      asciiTraceHelper.HookDefaultDropSinkWithoutContext<IslNetDevice> (device, "PhyRxDrop", theStream);
+
+      return;
+    }
+
+  //
+  // If we are provided an OutputStreamWrapper, we are expected to use it, and
+  // to providd a context.  We are free to come up with our own context if we
+  // want, and use the AsciiTraceHelper Hook*WithContext functions, but for
+  // compatibility and simplicity, we just use Config::Connect and let it deal
+  // with the context.
+  //
+  // Note that we are going to use the default trace sinks provided by the
+  // ascii trace helper.  There is actually no AsciiTraceHelper in sight here,
+  // but the default trace sinks are actually publicly available static
+  // functions that are always there waiting for just such a case.
+  //
+  uint32_t nodeid = nd->GetNode ()->GetId ();
+  uint32_t deviceid = nd->GetIfIndex ();
+  std::ostringstream oss;
+
+  oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::IslNetDevice/MacRx";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::IslNetDevice/TxQueue/Enqueue";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::IslNetDevice/TxQueue/Dequeue";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::IslNetDevice/TxQueue/Drop";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
+
+  oss.str ("");
+  oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::IslNetDevice/PhyRxDrop";
+  Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream));
+}
+
+NetDeviceContainer
+IslHelper::Install (NodeContainer c)
+{
+  std::vector<Ptr<Node> > nodes = std::vector<Ptr<Node> >(c.Begin(), c.End());
+  return Install (nodes);
+}
+
+NetDeviceContainer
+IslHelper::Install (std::vector<Ptr<Node> > &nodes)
+{
+  Ptr<IslChannel> channel = m_channelFactory.Create<IslChannel> ();
+
+  NetDeviceContainer container;
+
+  for (Ptr<Node> node: nodes)
+  {
+    Ptr<IslNetDevice> dev = m_deviceFactory.Create<IslNetDevice> ();
+    dev->SetAddress (Mac48Address::Allocate ());
+    node->AddDevice (dev);
+    Ptr<Queue<Packet> > queue = m_queueFactory.Create<Queue<Packet> > ();
+    dev->SetQueue (queue);
+    dev->Attach (channel);
+    container.Add (dev);
+  }
+
+  return container;
+}
+
+NetDeviceContainer
+IslHelper::Install (std::vector<std::string> &names)
+{
+  std::vector<Ptr<Node> > nodes;
+  for (std::string name : names)
+  {
+    Ptr<Node> node = Names::Find<Node>(name);
+    nodes.push_back (node);
+  }
+
+  return Install (nodes);
+}
+
+} // namespace ns3
diff --git a/helper/isl-helper.h b/helper/isl-helper.h
new file mode 100644
index 0000000..a811058
--- /dev/null
+++ b/helper/isl-helper.h
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef ISL_HELPER_H
+#define ISL_HELPER_H
+
+#include <string>
+
+#include <ns3/object-factory.h>
+#include <ns3/net-device-container.h>
+#include <ns3/node-container.h>
+
+#include <ns3/trace-helper.h>
+
+namespace ns3 {
+
+class NetDevice;
+class Node;
+
+/**
+ * \brief Build a set of IslNetDevice objects
+ *
+ * Normally we eschew multiple inheritance, however, the classes
+ * PcapUserHelperForDevice and AsciiTraceUserHelperForDevice are
+ * "mixins".
+ */
+class IslHelper : public PcapHelperForDevice,
+	                   public AsciiTraceHelperForDevice
+{
+public:
+  /**
+   * Create a IslHelper to make life easier when creating ISL networks.
+   */
+  IslHelper ();
+  virtual ~IslHelper () {}
+
+  /**
+   * Each point to point net device must have a queue to pass packets through.
+   * This method allows one to set the type of the queue that is automatically
+   * created when the device is created and attached to a node.
+   *
+   * \param type the type of queue
+   * \param n1 the name of the attribute to set on the queue
+   * \param v1 the value of the attribute to set on the queue
+   * \param n2 the name of the attribute to set on the queue
+   * \param v2 the value of the attribute to set on the queue
+   * \param n3 the name of the attribute to set on the queue
+   * \param v3 the value of the attribute to set on the queue
+   * \param n4 the name of the attribute to set on the queue
+   * \param v4 the value of the attribute to set on the queue
+   *
+   * Set the type of queue to create and associated to each
+   * IslNetDevice created through IslHelper::Install.
+   */
+  void SetQueue (std::string type,
+                 std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
+                 std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
+                 std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
+                 std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue ());
+
+
+  /**
+   * Set an attribute value to be propagated to each NetDevice created by the
+   * helper.
+   *
+   * \param name the name of the attribute to set
+   * \param value the value of the attribute to set
+   *
+   * Set these attributes on each ns3::IslNetDevice created
+   * by IslHelper::Install
+   */
+  void SetDeviceAttribute (std::string name, const AttributeValue &value);
+
+  /**
+   * Set an attribute value to be propagated to each Channel created by the
+   * helper.
+   *
+   * \param name the name of the attribute to set
+   * \param value the value of the attribute to set
+   *
+   * Set these attribute on each ns3::IslChannel created
+   * by IslHelper::Install
+   */
+  void SetChannelAttribute (std::string name, const AttributeValue &value);
+
+  /**
+   * \param c a set of nodes
+   * \return a NetDeviceContainer for nodes
+   *
+   * This method creates a ns3::IslChannel with the
+   * attributes configured by IslHelper::SetChannelAttribute,
+   * then, for each node in the input container, we create a
+   * ns3::IslNetDevice with the requested attributes,
+   * a queue for this ns3::NetDevice, and associate the resulting
+   * ns3::NetDevice with the ns3::Node and ns3::IslChannel.
+   */
+  NetDeviceContainer Install (NodeContainer c);
+
+  /**
+   * \param nodes Nodes
+   * \return a NetDeviceContainer for nodes
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   */
+  NetDeviceContainer Install (std::vector<Ptr<Node> > &nodes);
+
+  /**
+   * \param nodes Names of the nodes
+   * \return a NetDeviceContainer for nodes
+   *
+   * Saves you from having to construct a temporary NodeContainer.
+   */
+  NetDeviceContainer Install (std::vector<std::string> &nodes);
+
+private:
+  /**
+   * \brief Enable pcap output the indicated net device.
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * \param prefix Filename prefix to use for pcap files.
+   * \param nd Net device for which you want to enable tracing.
+   * \param promiscuous If true capture all possible packets available at the device.
+   * \param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  virtual void EnablePcapInternal (std::string prefix, Ptr<NetDevice> nd, bool promiscuous, bool explicitFilename);
+
+  /**
+   * \brief Enable ascii trace output on the indicated net device.
+   *
+   * NetDevice-specific implementation mechanism for hooking the trace and
+   * writing to the trace file.
+   *
+   * \param stream The output stream object to use when logging ascii traces.
+   * \param prefix Filename prefix to use for ascii trace files.
+   * \param nd Net device for which you want to enable tracing.
+   * \param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  virtual void EnableAsciiInternal (
+    Ptr<OutputStreamWrapper> stream,
+    std::string prefix,
+    Ptr<NetDevice> nd,
+    bool explicitFilename);
+
+  ObjectFactory m_queueFactory;         //!< Queue Factory
+  ObjectFactory m_channelFactory;       //!< Channel Factory
+  ObjectFactory m_deviceFactory;        //!< Device Factory
+};
+
+} // namespace ns3
+
+#endif /* ISL_HELPER_H */
diff --git a/helper/leo-helper.cc b/helper/leo-helper.cc
new file mode 100644
index 0000000..e8bf307
--- /dev/null
+++ b/helper/leo-helper.cc
@@ -0,0 +1,11 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "leo-helper.h"
+
+namespace ns3 {
+
+/* ... */
+
+
+}
+
diff --git a/helper/leo-helper.h b/helper/leo-helper.h
new file mode 100644
index 0000000..c2cfe88
--- /dev/null
+++ b/helper/leo-helper.h
@@ -0,0 +1,14 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#ifndef LEO_HELPER_H
+#define LEO_HELPER_H
+
+#include "ns3/leo.h"
+
+namespace ns3 {
+
+/* ... */
+
+}
+
+#endif /* LEO_HELPER_H */
+
diff --git a/model/isl-channel.cc b/model/isl-channel.cc
new file mode 100644
index 0000000..71ceb6b
--- /dev/null
+++ b/model/isl-channel.cc
@@ -0,0 +1,200 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <ns3/trace-source-accessor.h>
+#include <ns3/packet.h>
+#include <ns3/simulator.h>
+#include <ns3/log.h>
+#include <ns3/pointer.h>
+#include "isl-channel.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("IslChannel");
+
+NS_OBJECT_ENSURE_REGISTERED (IslChannel);
+
+TypeId
+IslChannel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IslChannel")
+    .SetParent<Channel> ()
+    .SetGroupName ("Leo")
+    .AddConstructor<IslChannel> ()
+    .AddAttribute ("PropagationDelay",
+                   "A propagation delay model for the channel.",
+                   PointerValue (),
+                   MakePointerAccessor (&IslChannel::m_propagationDelay),
+                   MakePointerChecker<PropagationDelayModel> ())
+    .AddAttribute ("PropagationLoss",
+                   "A propagation loss model for the channel.",
+                   PointerValue (),
+                   MakePointerAccessor (&IslChannel::m_propagationLoss),
+                   MakePointerChecker<PropagationLossModel> ())
+    .AddTraceSource ("TxRxIslChannel",
+                     "Trace source indicating transmission of packet "
+                     "from the IslChannel, used by the Animation "
+                     "interface.",
+                     MakeTraceSourceAccessor (&IslChannel::m_txrxIsl),
+                     "ns3::IslChannel::TxRxAnimationCallback")
+  ;
+  return tid;
+}
+
+//
+// By default, you get a channel that
+// has an "infitely" fast transmission speed and zero processing delay.
+IslChannel::IslChannel() : Channel (), m_link (0)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+IslChannel::~IslChannel()
+{
+}
+
+bool
+IslChannel::Detach (uint32_t deviceId)
+{
+  NS_LOG_FUNCTION (this << deviceId);
+  if (deviceId < m_link.size ())
+  {
+    if (!m_link[deviceId]->IsLinkUp ())
+    {
+      NS_LOG_WARN ("IslChannel::Detach(): Device is already detached (" << deviceId << ")");
+      return false;
+    }
+
+    m_link[deviceId]->NotifyLinkDown ();
+  }
+  else
+  {
+    return false;
+  }
+  return true;
+}
+
+int32_t
+IslChannel::Attach (Ptr<IslNetDevice> device)
+{
+  NS_LOG_FUNCTION (this << device);
+  NS_ASSERT (device != 0);
+  m_link.push_back(device);
+  return  m_link.size() - 1;
+}
+
+std::size_t
+IslChannel::GetNDevices (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_link.size ();
+}
+
+Ptr<NetDevice>
+IslChannel::GetDevice (std::size_t i) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_link[i];
+}
+
+bool IslChannel::Deliver (
+    Ptr<const Packet> p,
+    Ptr<IslNetDevice> src,
+    Ptr<IslNetDevice> dst,
+    Time txTime)
+{
+  Time delay = GetDelay (src, dst, txTime);
+
+  /* Check if there is LOS between the source and destination */
+  if (m_propagationLoss->CalcRxPower(1, src->GetMobilityModel(), dst->GetMobilityModel()) > 0)
+  {
+    Simulator::ScheduleWithContext (dst->GetNode ()->GetId (),
+        delay,
+        &IslNetDevice::Receive,
+        dst,
+        p->Copy ());
+
+    // Call the tx anim callback on the net device
+    m_txrxIsl (p, src, dst, txTime, delay);
+    return true;
+  }
+  else
+  {
+    NS_LOG_LOGIC (dst << " unreachable from " << src);
+
+    return false;
+  }
+}
+
+bool
+IslChannel::TransmitStart (
+    Ptr<const Packet> p,
+    uint32_t srcId,
+    Address destAddr,
+    Time txTime)
+{
+  NS_LOG_FUNCTION (destAddr << this << p << srcId);
+  NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
+
+  Ptr<IslNetDevice> src = m_link[srcId];
+  Ptr<IslNetDevice> dst = GetDevice (destAddr);
+
+  if (dst == nullptr)
+  {
+    NS_LOG_LOGIC ("destination address " << destAddr << " unknown on channel");
+    for (uint32_t i = 0; i < m_link.size (); i++)
+    {
+      Deliver (p, src, m_link[i], txTime);
+    }
+    return true;
+  }
+  else
+  {
+    return Deliver (p, src, dst, txTime);
+  }
+}
+
+Time
+IslChannel::GetDelay (Ptr<const IslNetDevice> src, Ptr<const IslNetDevice> dst, Time txTime) const
+{
+  NS_LOG_DEBUG ("Get delay from " << src << " to " << dst);
+
+  Ptr<MobilityModel> modSrc = src->GetMobilityModel ();
+  Ptr<MobilityModel> modDst = dst->GetMobilityModel ();
+
+  Time propagationDelay = m_propagationDelay->GetDelay (modSrc, modDst);
+
+  return txTime + propagationDelay;
+}
+
+// TODO optimize
+Ptr<IslNetDevice>
+IslChannel::GetDevice (Address &addr) const
+{
+  for (Ptr<IslNetDevice> dev : m_link)
+  {
+    if (dev->GetAddress () == addr)
+    {
+      return dev;
+    }
+  }
+
+  return 0;
+}
+
+} // namespace ns3
diff --git a/model/isl-channel.h b/model/isl-channel.h
new file mode 100644
index 0000000..de0c8c8
--- /dev/null
+++ b/model/isl-channel.h
@@ -0,0 +1,107 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef ISL_CHANNEL_H
+#define ISL_CHANNEL_H
+
+#include <string>
+#include <stdint.h>
+
+#include "ns3/object.h"
+#include "ns3/ptr.h"
+#include "ns3/channel.h"
+#include "ns3/mobility-model.h"
+#include "ns3/net-device.h"
+#include "ns3/time-data-calculators.h"
+#include "ns3/traced-callback.h"
+#include "ns3/mobility-module.h"
+#include "ns3/propagation-delay-model.h"
+#include "ns3/propagation-loss-model.h"
+#include "isl-net-device.h"
+
+namespace ns3 {
+
+class IslNetDevice;
+
+/**
+ * \ingroup network
+ * \defgroup channel Channel
+ */
+/**
+ * \ingroup channel
+ * \brief Simplified inter-satellite channel
+ *
+ * A perfect channel with varariable delay (time-of-flight).
+ *
+ */
+class IslChannel : public Channel
+{
+public:
+  static TypeId GetTypeId (void);
+
+  IslChannel ();
+  virtual ~IslChannel ();
+
+  /**
+   * \brief Attach a device to the channel.
+   * \param device Device to attach to the channel
+   * \return Index of the device inside the devices list
+   */
+  int32_t Attach (Ptr<IslNetDevice> device);
+
+  /**
+   * \brief Detach a given netdevice from this channel
+   * \param device pointer to the netdevice to detach from the channel
+   * \return true on success, false on failure
+   */
+  bool Detach (uint32_t deviceId);
+  virtual std::size_t GetNDevices (void) const;
+  virtual Ptr<NetDevice> GetDevice (std::size_t i) const;
+  virtual bool TransmitStart (Ptr<const Packet> p, uint32_t devId, Address dst, Time txTime);
+
+protected:
+  /**
+   * \brief Get the delay associated with this channel
+   * \returns Time delay
+   */
+  Time GetDelay (Ptr<const IslNetDevice> first, Ptr<const IslNetDevice> second, Time txTime) const;
+
+private:
+
+  Ptr<IslNetDevice> GetDevice (Address &addr) const;
+
+  TracedCallback<Ptr<const Packet>,     // Packet being transmitted
+                 Ptr<NetDevice>,  // Transmitting NetDevice
+                 Ptr<NetDevice>,  // Receiving NetDevice
+                 Time,                  // Amount of time to transmit the pkt
+                 Time                   // Last bit receive time (relative to now)
+                 > m_txrxIsl;
+  /**
+   * \brief Propagation delay model to be used with this channel
+   */
+  Ptr<PropagationDelayModel> m_propagationDelay;
+  /**
+   * \brief Propagation loss model to be used with this channel
+   */
+  Ptr<PropagationLossModel> m_propagationLoss;
+  std::vector<Ptr<IslNetDevice> > m_link;
+
+  bool Deliver (Ptr<const Packet> p, Ptr<IslNetDevice> src, Ptr<IslNetDevice> dst, Time txTime);
+}; // class IslChannel
+
+} // namespace ns3
+
+#endif /* ISL_CHANNEL_H */
diff --git a/model/isl-net-device.cc b/model/isl-net-device.cc
new file mode 100644
index 0000000..00399e9
--- /dev/null
+++ b/model/isl-net-device.cc
@@ -0,0 +1,742 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "ns3/log.h"
+#include "ns3/queue.h"
+#include "ns3/simulator.h"
+#include "ns3/mac48-address.h"
+#include "ns3/llc-snap-header.h"
+#include "ns3/error-model.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/uinteger.h"
+#include "ns3/pointer.h"
+#include "ns3/net-device-queue-interface.h"
+#include "ns3/ppp-header.h"
+#include "isl-channel.h"
+#include "isl-net-device.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("IslNetDevice");
+
+NS_OBJECT_ENSURE_REGISTERED (IslNetDevice);
+
+TypeId
+IslNetDevice::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IslNetDevice")
+    .SetParent<NetDevice> ()
+    .SetGroupName ("Leo")
+    .AddConstructor<IslNetDevice> ()
+    .AddAttribute ("Mtu", "The MAC-level Maximum Transmission Unit",
+                   UintegerValue (DEFAULT_MTU),
+                   MakeUintegerAccessor (&IslNetDevice::SetMtu,
+                                         &IslNetDevice::GetMtu),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("Address",
+                   "The MAC address of this device.",
+                   Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
+                   MakeMac48AddressAccessor (&IslNetDevice::m_address),
+                   MakeMac48AddressChecker ())
+    .AddAttribute ("DataRate",
+                   "The default data rate for point to point links",
+                   DataRateValue (DataRate ("32768b/s")),
+                   MakeDataRateAccessor (&IslNetDevice::m_bps),
+                   MakeDataRateChecker ())
+    .AddAttribute ("ReceiveErrorModel",
+                   "The receiver error model used to simulate packet loss",
+                   PointerValue (),
+                   MakePointerAccessor (&IslNetDevice::m_receiveErrorModel),
+                   MakePointerChecker<ErrorModel> ())
+    .AddAttribute ("InterframeGap",
+                   "The time to wait between packet (frame) transmissions",
+                   TimeValue (Seconds (0.0)),
+                   MakeTimeAccessor (&IslNetDevice::m_tInterframeGap),
+                   MakeTimeChecker ())
+
+    //
+    // Transmit queueing discipline for the device which includes its own set
+    // of trace hooks.
+    //
+    .AddAttribute ("TxQueue",
+                   "A queue to use as the transmit queue in the device.",
+                   PointerValue (),
+                   MakePointerAccessor (&IslNetDevice::m_queue),
+                   MakePointerChecker<Queue<Packet> > ())
+    .AddAttribute ("MobilityModel", "The mobility model of the device",
+                   PointerValue (),
+                   MakePointerAccessor (&IslNetDevice::SetMobilityModel,
+                     &IslNetDevice::GetMobilityModel),
+                   MakePointerChecker<MobilityModel> ())
+    //
+    // Trace sources at the "top" of the net device, where packets transition
+    // to/from higher layers.
+    //
+    .AddTraceSource ("MacTx",
+                     "Trace source indicating a packet has arrived "
+                     "for transmission by this device",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_macTxTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("MacTxDrop",
+                     "Trace source indicating a packet has been dropped "
+                     "by the device before transmission",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_macTxDropTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("MacPromiscRx",
+                     "A packet has been received by this device, "
+                     "has been passed up from the physical layer "
+                     "and is being forwarded up the local protocol stack.  "
+                     "This is a promiscuous trace,",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_macPromiscRxTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("MacRx",
+                     "A packet has been received by this device, "
+                     "has been passed up from the physical layer "
+                     "and is being forwarded up the local protocol stack.  "
+                     "This is a non-promiscuous trace,",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_macRxTrace),
+                     "ns3::Packet::TracedCallback")
+#if 0
+    // Not currently implemented for this device
+    .AddTraceSource ("MacRxDrop",
+                     "Trace source indicating a packet was dropped "
+                     "before being forwarded up the stack",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_macRxDropTrace),
+                     "ns3::Packet::TracedCallback")
+#endif
+    //
+    // Trace sources at the "bottom" of the net device, where packets transition
+    // to/from the channel.
+    //
+    .AddTraceSource ("PhyTxBegin",
+                     "Trace source indicating a packet has begun "
+                     "transmitting over the channel",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyTxBeginTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("PhyTxEnd",
+                     "Trace source indicating a packet has been "
+                     "completely transmitted over the channel",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyTxEndTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("PhyTxDrop",
+                     "Trace source indicating a packet has been "
+                     "dropped by the device during transmission",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyTxDropTrace),
+                     "ns3::Packet::TracedCallback")
+#if 0
+    // Not currently implemented for this device
+    .AddTraceSource ("PhyRxBegin",
+                     "Trace source indicating a packet has begun "
+                     "being received by the device",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyRxBeginTrace),
+                     "ns3::Packet::TracedCallback")
+#endif
+    .AddTraceSource ("PhyRxEnd",
+                     "Trace source indicating a packet has been "
+                     "completely received by the device",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyRxEndTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("PhyRxDrop",
+                     "Trace source indicating a packet has been "
+                     "dropped by the device during reception",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_phyRxDropTrace),
+                     "ns3::Packet::TracedCallback")
+
+    //
+    // Trace sources designed to simulate a packet sniffer facility (tcpdump).
+    // Note that there is really no difference between promiscuous and
+    // non-promiscuous traces in a point-to-point link.
+    //
+    .AddTraceSource ("Sniffer",
+                    "Trace source simulating a non-promiscuous packet sniffer "
+                     "attached to the device",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_snifferTrace),
+                     "ns3::Packet::TracedCallback")
+    .AddTraceSource ("PromiscSniffer",
+                     "Trace source simulating a promiscuous packet sniffer "
+                     "attached to the device",
+                     MakeTraceSourceAccessor (&IslNetDevice::m_promiscSnifferTrace),
+                     "ns3::Packet::TracedCallback")
+  ;
+  return tid;
+}
+
+IslNetDevice::IslNetDevice ()
+  :
+    m_txMachineState (READY),
+    m_channel (0),
+    m_linkUp (false),
+    m_currentPkt (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+IslNetDevice::~IslNetDevice ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+IslNetDevice::AddHeader (Ptr<Packet> p, uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (this << p << protocolNumber);
+  PppHeader ppp;
+  ppp.SetProtocol (EtherToPpp (protocolNumber));
+  p->AddHeader (ppp);
+}
+
+bool
+IslNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t& param)
+{
+  NS_LOG_FUNCTION (this << p << param);
+  PppHeader ppp;
+  p->RemoveHeader (ppp);
+  param = PppToEther (ppp.GetProtocol ());
+  return true;
+}
+
+void
+IslNetDevice::DoInitialize (void)
+{
+  if (m_queueInterface)
+    {
+      NS_ASSERT_MSG (m_queue != 0, "A Queue object has not been attached to the device");
+
+      // connect the traced callbacks of m_queue to the static methods provided by
+      // the NetDeviceQueue class to support flow control and dynamic queue limits.
+      // This could not be done in NotifyNewAggregate because at that time we are
+      // not guaranteed that a queue has been attached to the netdevice
+      m_queueInterface->GetTxQueue (0)->ConnectQueueTraces (m_queue);
+    }
+
+  NetDevice::DoInitialize ();
+}
+
+void
+IslNetDevice::NotifyNewAggregate (void)
+{
+  NS_LOG_FUNCTION (this);
+  if (m_queueInterface == 0)
+    {
+      Ptr<NetDeviceQueueInterface> ndqi = this->GetObject<NetDeviceQueueInterface> ();
+      //verify that it's a valid netdevice queue interface and that
+      //the netdevice queue interface was not set before
+      if (ndqi != 0)
+        {
+          m_queueInterface = ndqi;
+        }
+    }
+  NetDevice::NotifyNewAggregate ();
+}
+
+void
+IslNetDevice::DoDispose ()
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  m_channel = 0;
+  m_receiveErrorModel = 0;
+  m_currentPkt = 0;
+  m_queue = 0;
+  m_queueInterface = 0;
+  NetDevice::DoDispose ();
+}
+
+void
+IslNetDevice::SetDataRate (DataRate bps)
+{
+  NS_LOG_FUNCTION (this);
+  m_bps = bps;
+}
+
+void
+IslNetDevice::SetInterframeGap (Time t)
+{
+  NS_LOG_FUNCTION (this << t.GetSeconds ());
+  m_tInterframeGap = t;
+}
+
+bool
+IslNetDevice::TransmitStart (Ptr<Packet> p, const Address &dest)
+{
+  NS_LOG_FUNCTION (this << p);
+  NS_LOG_LOGIC ("UID is " << p->GetUid () << ")");
+
+  //
+  // This function is called to start the process of transmitting a packet.
+  // We need to tell the channel that we've started wiggling the wire and
+  // schedule an event that will be executed when the transmission is complete.
+  //
+  NS_ASSERT_MSG (m_txMachineState == READY, "Must be READY to transmit");
+  m_txMachineState = BUSY;
+  m_currentPkt = p;
+  m_phyTxBeginTrace (m_currentPkt);
+
+  Time txTime = m_bps.CalculateBytesTxTime (p->GetSize ());
+  Time txCompleteTime = txTime + m_tInterframeGap;
+
+  NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << txCompleteTime.GetSeconds () << "sec");
+  Simulator::Schedule (txCompleteTime, &IslNetDevice::TransmitComplete, this, dest);
+
+  bool result = m_channel->TransmitStart (p, m_channelDevId, dest, txTime);
+  if (result == false)
+    {
+      m_phyTxDropTrace (p);
+    }
+  return result;
+}
+
+void
+IslNetDevice::TransmitComplete (const Address &dest)
+{
+  NS_LOG_FUNCTION (this);
+
+  //
+  // This function is called to when we're all done transmitting a packet.
+  // We try and pull another packet off of the transmit queue.  If the queue
+  // is empty, we are done, otherwise we need to start transmitting the
+  // next packet.
+  //
+  NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
+  m_txMachineState = READY;
+
+  NS_ASSERT_MSG (m_currentPkt != 0, "IslNetDevice::TransmitComplete(): m_currentPkt zero");
+
+  m_phyTxEndTrace (m_currentPkt);
+  m_currentPkt = 0;
+
+  Ptr<Packet> p = m_queue->Dequeue ();
+  if (p == 0)
+    {
+      NS_LOG_LOGIC ("No pending packets in device queue after tx complete");
+      return;
+    }
+
+  //
+  // Got another packet off of the queue, so start the transmit process again.
+  //
+  m_snifferTrace (p);
+  m_promiscSnifferTrace (p);
+  TransmitStart (p, dest);
+}
+
+bool
+IslNetDevice::Attach (Ptr<IslChannel> ch)
+{
+  NS_LOG_FUNCTION (this << &ch);
+
+  m_channel = ch;
+
+  m_channelDevId = m_channel->Attach (this);
+
+  //
+  // This device is up whenever it is attached to a channel.  A better plan
+  // would be to have the link come up when both devices are attached, but this
+  // is not done for now.
+  //
+  NotifyLinkUp ();
+  return true;
+}
+
+void
+IslNetDevice::SetQueue (Ptr<Queue<Packet> > q)
+{
+  NS_LOG_FUNCTION (this << q);
+  m_queue = q;
+}
+
+void
+IslNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
+{
+  NS_LOG_FUNCTION (this << em);
+  m_receiveErrorModel = em;
+}
+
+void
+IslNetDevice::Receive (Ptr<Packet> packet)
+{
+  NS_LOG_FUNCTION (this << packet);
+  uint16_t protocol = 0;
+
+  if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
+    {
+      //
+      // If we have an error model and it indicates that it is time to lose a
+      // corrupted packet, don't forward this packet up, let it go.
+      //
+      m_phyRxDropTrace (packet);
+    }
+  else
+    {
+      //
+      // Hit the trace hooks.  All of these hooks are in the same place in this
+      // device because it is so simple, but this is not usually the case in
+      // more complicated devices.
+      //
+      m_snifferTrace (packet);
+      m_promiscSnifferTrace (packet);
+      m_phyRxEndTrace (packet);
+
+      //
+      // Trace sinks will expect complete packets, not packets without some of the
+      // headers.
+      //
+      Ptr<Packet> originalPacket = packet->Copy ();
+
+      //
+      // Strip off the point-to-point protocol header and forward this packet
+      // up the protocol stack.  Since this is a simple point-to-point link,
+      // there is no difference in what the promisc callback sees and what the
+      // normal receive callback sees.
+      //
+      ProcessHeader (packet, protocol);
+
+      if (!m_promiscCallback.IsNull ())
+        {
+          m_macPromiscRxTrace (originalPacket);
+          m_promiscCallback (this, packet, protocol, GetRemote (), GetAddress (), NetDevice::PACKET_HOST);
+        }
+
+      m_macRxTrace (originalPacket);
+      m_rxCallback (this, packet, protocol, GetRemote ());
+    }
+}
+
+Ptr<Queue<Packet> >
+IslNetDevice::GetQueue (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_queue;
+}
+
+void
+IslNetDevice::NotifyLinkUp (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_linkUp = true;
+  m_linkChangeCallbacks ();
+}
+
+void
+IslNetDevice::NotifyLinkDown (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_linkUp = false;
+  m_linkChangeCallbacks ();
+}
+
+void
+IslNetDevice::SetIfIndex (const uint32_t index)
+{
+  NS_LOG_FUNCTION (this);
+  m_ifIndex = index;
+}
+
+uint32_t
+IslNetDevice::GetIfIndex (void) const
+{
+  return m_ifIndex;
+}
+
+Ptr<Channel>
+IslNetDevice::GetChannel (void) const
+{
+  return m_channel;
+}
+
+//
+// This is a point-to-point device, so we really don't need any kind of address
+// information.  However, the base class NetDevice wants us to define the
+// methods to get and set the address.  Rather than be rude and assert, we let
+// clients get and set the address, but simply ignore them.
+
+void
+IslNetDevice::SetAddress (Address address)
+{
+  NS_LOG_FUNCTION (this << address);
+  m_address = Mac48Address::ConvertFrom (address);
+}
+
+Address
+IslNetDevice::GetAddress (void) const
+{
+  return m_address;
+}
+
+bool
+IslNetDevice::IsLinkUp (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_linkUp;
+}
+
+void
+IslNetDevice::AddLinkChangeCallback (Callback<void> callback)
+{
+  NS_LOG_FUNCTION (this);
+  m_linkChangeCallbacks.ConnectWithoutContext (callback);
+}
+
+//
+// This is a point-to-point device, so every transmission is a broadcast to
+// all of the devices on the network.
+//
+bool
+IslNetDevice::IsBroadcast (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+//
+// We don't really need any addressing information since this is a
+// point-to-point device.  The base class NetDevice wants us to return a
+// broadcast address, so we make up something reasonable.
+//
+Address
+IslNetDevice::GetBroadcast (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return Mac48Address ("ff:ff:ff:ff:ff:ff");
+}
+
+bool
+IslNetDevice::IsMulticast (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+Address
+IslNetDevice::GetMulticast (Ipv4Address multicastGroup) const
+{
+  NS_LOG_FUNCTION (this);
+  return Mac48Address ("01:00:5e:00:00:00");
+}
+
+Address
+IslNetDevice::GetMulticast (Ipv6Address addr) const
+{
+  NS_LOG_FUNCTION (this << addr);
+  return Mac48Address ("33:33:00:00:00:00");
+}
+
+bool
+IslNetDevice::IsIsl (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+bool
+IslNetDevice::IsBridge (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return false;
+}
+
+bool
+IslNetDevice::Send (
+  Ptr<Packet> packet,
+  const Address &dest,
+  uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (this << packet << dest << protocolNumber);
+  NS_LOG_LOGIC ("p=" << packet << ", dest=" << &dest);
+  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
+
+  //
+  // If IsLinkUp() is false it means there is no channel to send any packet
+  // over so we just hit the drop trace on the packet and return an error.
+  //
+  if (IsLinkUp () == false)
+    {
+      m_macTxDropTrace (packet);
+      return false;
+    }
+
+  //
+  // Stick a point to point protocol header on the packet in preparation for
+  // shoving it out the door.
+  //
+  AddHeader (packet, protocolNumber);
+
+  m_macTxTrace (packet);
+
+  //
+  // We should enqueue and dequeue the packet to hit the tracing hooks.
+  //
+  if (m_queue->Enqueue (packet))
+    {
+      //
+      // If the channel is ready for transition we send the packet right now
+      //
+      if (m_txMachineState == READY)
+        {
+          packet = m_queue->Dequeue ();
+          m_snifferTrace (packet);
+          m_promiscSnifferTrace (packet);
+          bool ret = TransmitStart (packet, dest);
+          return ret;
+        }
+      return true;
+    }
+
+  // Enqueue may fail (overflow)
+
+  m_macTxDropTrace (packet);
+  return false;
+}
+
+bool
+IslNetDevice::SendFrom (Ptr<Packet> packet,
+                                 const Address &source,
+                                 const Address &dest,
+                                 uint16_t protocolNumber)
+{
+  NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);
+  return false;
+}
+
+Ptr<Node>
+IslNetDevice::GetNode (void) const
+{
+  return m_node;
+}
+
+void
+IslNetDevice::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = node;
+}
+
+bool
+IslNetDevice::NeedsArp (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return true;
+}
+
+void
+IslNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
+{
+  m_rxCallback = cb;
+}
+
+void
+IslNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
+{
+  m_promiscCallback = cb;
+}
+
+bool
+IslNetDevice::SupportsSendFrom (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return false;
+}
+
+void
+IslNetDevice::DoMpiReceive (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (this << p);
+  Receive (p);
+}
+
+Address
+IslNetDevice::GetRemote (void) const
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT (m_channel->GetNDevices () == 2);
+  for (std::size_t i = 0; i < m_channel->GetNDevices (); ++i)
+    {
+      Ptr<NetDevice> tmp = m_channel->GetDevice (i);
+      if (tmp != this)
+        {
+          return tmp->GetAddress ();
+        }
+    }
+  NS_ASSERT (false);
+  // quiet compiler.
+  return Address ();
+}
+
+bool
+IslNetDevice::SetMtu (uint16_t mtu)
+{
+  NS_LOG_FUNCTION (this << mtu);
+  m_mtu = mtu;
+  return true;
+}
+
+uint16_t
+IslNetDevice::GetMtu (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_mtu;
+}
+
+uint16_t
+IslNetDevice::PppToEther (uint16_t proto)
+{
+  NS_LOG_FUNCTION_NOARGS();
+  switch(proto)
+    {
+    case 0x0021: return 0x0800;   //IPv4
+    case 0x0057: return 0x86DD;   //IPv6
+    case 2054: return 0x0806;   //ARP
+    default: NS_ASSERT_MSG (false, "PPP Protocol number not defined!");
+    }
+  return 0;
+}
+
+uint16_t
+IslNetDevice::EtherToPpp (uint16_t proto)
+{
+  NS_LOG_FUNCTION_NOARGS();
+  switch(proto)
+    {
+    case 0x0800: return 0x0021;   //IPv4
+    case 0x86DD: return 0x0057;   //IPv6
+    case 0x0806: return 2054;   //ARP
+    default: NS_ASSERT_MSG (false, "PPP Protocol number not defined!");
+    }
+  return 0;
+}
+
+Ptr<MobilityModel>
+IslNetDevice::GetMobilityModel (void) const
+{
+  return m_mobilityModel;
+}
+
+void
+IslNetDevice::SetMobilityModel (Ptr<MobilityModel> model)
+{
+  NS_LOG_FUNCTION (this);
+  m_mobilityModel = model;
+}
+
+bool
+IslNetDevice::IsPointToPoint() const
+{
+  return true;
+}
+
+} // namespace ns3
diff --git a/model/isl-net-device.h b/model/isl-net-device.h
new file mode 100644
index 0000000..a87619f
--- /dev/null
+++ b/model/isl-net-device.h
@@ -0,0 +1,499 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * 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 ISL_NET_DEVICE_H
+#define ISL_NET_DEVICE_H
+
+#include <cstring>
+
+#include "ns3/address.h"
+#include "ns3/node.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/packet.h"
+#include "ns3/traced-callback.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+#include "ns3/ptr.h"
+#include "ns3/mac48-address.h"
+#include "ns3/mobility-model.h"
+
+namespace ns3 {
+
+template <typename Item> class Queue;
+class NetDeviceQueueInterface;
+class IslChannel;
+class ErrorModel;
+
+/**
+ * \defgroup point-to-point Point-To-Point Network Device
+ * This section documents the API of the ns-3 point-to-point module. For a
+ * functional description, please refer to the ns-3 manual here:
+ * http://www.nsnam.org/docs/models/html/point-to-point.html
+ *
+ * Be sure to read the manual BEFORE going down to the API.
+ */
+
+/**
+ * \ingroup point-to-point
+ * \class IslNetDevice
+ * \brief A Device for a Point to Point Network Link.
+ *
+ * This IslNetDevice class specializes the NetDevice abstract
+ * base class.  Together with a IslChannel (and a peer
+ * IslNetDevice), the class models, with some level of
+ * abstraction, a generic point-to-point or serial link.
+ * Key parameters or objects that can be specified for this device
+ * include a queue, data rate, and interframe transmission gap (the
+ * propagation delay is set in the IslChannel).
+ */
+class IslNetDevice : public NetDevice
+{
+public:
+  /**
+   * \brief Get the TypeId
+   *
+   * \return The TypeId for this class
+   */
+  static TypeId GetTypeId (void);
+
+  /**
+   * Construct a IslNetDevice
+   *
+   * This is the constructor for the IslNetDevice.  It takes as a
+   * parameter a pointer to the Node to which this device is connected,
+   * as well as an optional DataRate object.
+   */
+  IslNetDevice ();
+
+  /**
+   * Destroy a IslNetDevice
+   *
+   * This is the destructor for the IslNetDevice.
+   */
+  virtual ~IslNetDevice ();
+
+  /**
+   * Set the Data Rate used for transmission of packets.  The data rate is
+   * set in the Attach () method from the corresponding field in the channel
+   * to which the device is attached.  It can be overridden using this method.
+   *
+   * \param bps the data rate at which this object operates
+   */
+  void SetDataRate (DataRate bps);
+
+  /**
+   * Set the interframe gap used to separate packets.  The interframe gap
+   * defines the minimum space required between packets sent by this device.
+   *
+   * \param t the interframe gap time
+   */
+  void SetInterframeGap (Time t);
+
+  /**
+   * Attach the device to a channel.
+   *
+   * \param ch Ptr to the channel to which this object is being attached.
+   * \return true if the operation was successful (always true actually)
+   */
+  bool Attach (Ptr<IslChannel> ch);
+
+  /**
+   * Attach a queue to the IslNetDevice.
+   *
+   * The IslNetDevice "owns" a queue that implements a queueing
+   * method such as DropTailQueue or RedQueue
+   *
+   * \param queue Ptr to the new queue.
+   */
+  void SetQueue (Ptr<Queue<Packet> > queue);
+
+  /**
+   * Get a copy of the attached Queue.
+   *
+   * \returns Ptr to the queue.
+   */
+  Ptr<Queue<Packet> > GetQueue (void) const;
+
+  /**
+   * Attach a receive ErrorModel to the IslNetDevice.
+   *
+   * The IslNetDevice may optionally include an ErrorModel in
+   * the packet receive chain.
+   *
+   * \param em Ptr to the ErrorModel.
+   */
+  void SetReceiveErrorModel (Ptr<ErrorModel> em);
+
+  /**
+   * Receive a packet from a connected IslChannel.
+   *
+   * The IslNetDevice receives packets from its connected channel
+   * and forwards them up the protocol stack.  This is the public method
+   * used by the channel to indicate that the last bit of a packet has
+   * arrived at the device.
+   *
+   * \param p Ptr to the received packet.
+   */
+  void Receive (Ptr<Packet> p);
+
+  // The remaining methods are documented in ns3::NetDevice*
+
+  virtual void SetIfIndex (const uint32_t index);
+  virtual uint32_t GetIfIndex (void) const;
+
+  virtual Ptr<Channel> GetChannel (void) const;
+
+  virtual void SetAddress (Address address);
+  virtual Address GetAddress (void) const;
+
+  virtual bool SetMtu (const uint16_t mtu);
+  virtual uint16_t GetMtu (void) const;
+
+  virtual bool IsLinkUp (void) const;
+
+  virtual void AddLinkChangeCallback (Callback<void> callback);
+
+  virtual bool IsBroadcast (void) const;
+  virtual Address GetBroadcast (void) const;
+
+  virtual bool IsMulticast (void) const;
+  virtual Address GetMulticast (Ipv4Address multicastGroup) const;
+
+  virtual bool IsIsl (void) const;
+  virtual bool IsBridge (void) const;
+
+  virtual bool IsPointToPoint() const;
+
+  virtual bool Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);
+  virtual bool SendFrom (Ptr<Packet> packet, const Address& source, const Address& dest, uint16_t protocolNumber);
+
+  virtual Ptr<Node> GetNode (void) const;
+  virtual void SetNode (Ptr<Node> node);
+
+  virtual bool NeedsArp (void) const;
+
+  virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);
+
+  virtual Address GetMulticast (Ipv6Address addr) const;
+
+  virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);
+  virtual bool SupportsSendFrom (void) const;
+
+  Ptr<MobilityModel> GetMobilityModel (void) const;
+  void SetMobilityModel (Ptr<MobilityModel> model);
+  void NotifyLinkDown (void);
+
+protected:
+  /**
+   * \brief Handler for MPI receive event
+   *
+   * \param p Packet received
+   */
+  void DoMpiReceive (Ptr<Packet> p);
+
+  virtual void DoInitialize (void);
+  virtual void NotifyNewAggregate (void);
+
+private:
+
+  /**
+   * \brief Assign operator
+   *
+   * The method is private, so it is DISABLED.
+   *
+   * \param o Other NetDevice
+   * \return New instance of the NetDevice
+   */
+  IslNetDevice& operator = (const IslNetDevice &o);
+
+  /**
+   * \brief Copy constructor
+   *
+   * The method is private, so it is DISABLED.
+
+   * \param o Other NetDevice
+   */
+  IslNetDevice (const IslNetDevice &o);
+
+  /**
+   * \brief Dispose of the object
+   */
+  virtual void DoDispose (void);
+
+private:
+
+  /**
+   * \returns the address of the remote device connected to this device
+   * through the point to point channel.
+   */
+  Address GetRemote (void) const;
+
+  /**
+   * Adds the necessary headers and trailers to a packet of data in order to
+   * respect the protocol implemented by the agent.
+   * \param p packet
+   * \param protocolNumber protocol number
+   */
+  void AddHeader (Ptr<Packet> p, uint16_t protocolNumber);
+
+  /**
+   * Removes, from a packet of data, all headers and trailers that
+   * relate to the protocol implemented by the agent
+   * \param p Packet whose headers need to be processed
+   * \param param An integer parameter that can be set by the function
+   * \return Returns true if the packet should be forwarded up the
+   * protocol stack.
+   */
+  bool ProcessHeader (Ptr<Packet> p, uint16_t& param);
+
+  /**
+   * Start Sending a Packet Down the Wire.
+   *
+   * The TransmitStart method is the method that is used internally in the
+   * IslNetDevice to begin the process of sending a packet out on
+   * the channel.  The corresponding method is called on the channel to let
+   * it know that the physical device this class represents has virtually
+   * started sending signals.  An event is scheduled for the time at which
+   * the bits have been completely transmitted.
+   *
+   * \see IslChannel::TransmitStart ()
+   * \see TransmitComplete()
+   * \param p a reference to the packet to send
+   * \returns true if success, false on failure
+   */
+  bool TransmitStart (Ptr<Packet> p, const Address &dest);
+
+  /**
+   * Stop Sending a Packet Down the Wire and Begin the Interframe Gap.
+   *
+   * The TransmitComplete method is used internally to finish the process
+   * of sending a packet out on the channel.
+   */
+  void TransmitComplete (const Address &dest);
+
+  /**
+   * \brief Make the link up and running
+   *
+   * It calls also the linkChange callback.
+   */
+  void NotifyLinkUp (void);
+
+  /**
+   * Enumeration of the states of the transmit machine of the net device.
+   */
+  enum TxMachineState
+  {
+    READY,   /**< The transmitter is ready to begin transmission of a packet */
+    BUSY     /**< The transmitter is busy transmitting a packet */
+  };
+  /**
+   * The state of the Net Device transmit state machine.
+   */
+  TxMachineState m_txMachineState;
+
+  /**
+   * The data rate that the Net Device uses to simulate packet transmission
+   * timing.
+   */
+  DataRate       m_bps;
+
+  /**
+   * The interframe gap that the Net Device uses to throttle packet
+   * transmission
+   */
+  Time           m_tInterframeGap;
+
+  /**
+   * The IslChannel to which this IslNetDevice has been
+   * attached.
+   */
+  Ptr<IslChannel> m_channel;
+
+  /**
+   * The Queue which this IslNetDevice uses as a packet source.
+   * Management of this Queue has been delegated to the IslNetDevice
+   * and it has the responsibility for deletion.
+   * \see class DropTailQueue
+   */
+  Ptr<Queue<Packet> > m_queue;
+
+  /**
+   * Error model for receive packet events
+   */
+  Ptr<ErrorModel> m_receiveErrorModel;
+
+  /**
+   * The trace source fired when packets come into the "top" of the device
+   * at the L3/L2 transition, before being queued for transmission.
+   */
+  TracedCallback<Ptr<const Packet> > m_macTxTrace;
+
+  /**
+   * The trace source fired when packets coming into the "top" of the device
+   * at the L3/L2 transition are dropped before being queued for transmission.
+   */
+  TracedCallback<Ptr<const Packet> > m_macTxDropTrace;
+
+  /**
+   * The trace source fired for packets successfully received by the device
+   * immediately before being forwarded up to higher layers (at the L2/L3
+   * transition).  This is a promiscuous trace (which doesn't mean a lot here
+   * in the point-to-point device).
+   */
+  TracedCallback<Ptr<const Packet> > m_macPromiscRxTrace;
+
+  /**
+   * The trace source fired for packets successfully received by the device
+   * immediately before being forwarded up to higher layers (at the L2/L3
+   * transition).  This is a non-promiscuous trace (which doesn't mean a lot
+   * here in the point-to-point device).
+   */
+  TracedCallback<Ptr<const Packet> > m_macRxTrace;
+
+  /**
+   * The trace source fired for packets successfully received by the device
+   * but are dropped before being forwarded up to higher layers (at the L2/L3
+   * transition).
+   */
+  TracedCallback<Ptr<const Packet> > m_macRxDropTrace;
+
+  /**
+   * The trace source fired when a packet begins the transmission process on
+   * the medium.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyTxBeginTrace;
+
+  /**
+   * The trace source fired when a packet ends the transmission process on
+   * the medium.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyTxEndTrace;
+
+  /**
+   * The trace source fired when the phy layer drops a packet before it tries
+   * to transmit it.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyTxDropTrace;
+
+  /**
+   * The trace source fired when a packet begins the reception process from
+   * the medium -- when the simulated first bit(s) arrive.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyRxBeginTrace;
+
+  /**
+   * The trace source fired when a packet ends the reception process from
+   * the medium.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyRxEndTrace;
+
+  /**
+   * The trace source fired when the phy layer drops a packet it has received.
+   * This happens if the receiver is not enabled or the error model is active
+   * and indicates that the packet is corrupt.
+   */
+  TracedCallback<Ptr<const Packet> > m_phyRxDropTrace;
+
+  /**
+   * A trace source that emulates a non-promiscuous protocol sniffer connected
+   * to the device.  Unlike your average everyday sniffer, this trace source
+   * will not fire on PACKET_OTHERHOST events.
+   *
+   * On the transmit size, this trace hook will fire after a packet is dequeued
+   * from the device queue for transmission.  In Linux, for example, this would
+   * correspond to the point just before a device \c hard_start_xmit where
+   * \c dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
+   * ETH_P_ALL handlers.
+   *
+   * On the receive side, this trace hook will fire when a packet is received,
+   * just before the receive callback is executed.  In Linux, for example,
+   * this would correspond to the point at which the packet is dispatched to
+   * packet sniffers in \c netif_receive_skb.
+   */
+  TracedCallback<Ptr<const Packet> > m_snifferTrace;
+
+  /**
+   * A trace source that emulates a promiscuous mode protocol sniffer connected
+   * to the device.  This trace source fire on packets destined for any host
+   * just like your average everyday packet sniffer.
+   *
+   * On the transmit size, this trace hook will fire after a packet is dequeued
+   * from the device queue for transmission.  In Linux, for example, this would
+   * correspond to the point just before a device \c hard_start_xmit where
+   * \c dev_queue_xmit_nit is called to dispatch the packet to the PF_PACKET
+   * ETH_P_ALL handlers.
+   *
+   * On the receive side, this trace hook will fire when a packet is received,
+   * just before the receive callback is executed.  In Linux, for example,
+   * this would correspond to the point at which the packet is dispatched to
+   * packet sniffers in \c netif_receive_skb.
+   */
+  TracedCallback<Ptr<const Packet> > m_promiscSnifferTrace;
+
+  Ptr<Node> m_node;         //!< Node owning this NetDevice
+  Ptr<NetDeviceQueueInterface> m_queueInterface;   //!< NetDevice queue interface
+  Mac48Address m_address;   //!< Mac48Address of this NetDevice
+  NetDevice::ReceiveCallback m_rxCallback;   //!< Receive callback
+  NetDevice::PromiscReceiveCallback m_promiscCallback;  //!< Receive callback
+                                                        //   (promisc data)
+  uint32_t m_ifIndex; //!< Index of the interface
+  bool m_linkUp;      //!< Identify if the link is up or not
+  TracedCallback<> m_linkChangeCallbacks;  //!< Callback for the link change event
+
+  static const uint16_t DEFAULT_MTU = 1500; //!< Default MTU
+
+  /**
+   * \brief The Maximum Transmission Unit
+   *
+   * This corresponds to the maximum
+   * number of bytes that can be transmitted as seen from higher layers.
+   * This corresponds to the 1500 byte MTU size often seen on IP over
+   * Ethernet.
+   */
+  uint32_t m_mtu;
+
+  /**
+   * \brief The index into the network device list of the channel.
+   *
+   * This is written to when the device is attached.
+   */
+  uint32_t m_channelDevId;
+
+  Ptr<Packet> m_currentPkt; //!< Current packet processed
+
+  Ptr<MobilityModel> m_mobilityModel;
+
+  /**
+   * \brief PPP to Ethernet protocol number mapping
+   * \param protocol A PPP protocol number
+   * \return The corresponding Ethernet protocol number
+   */
+  static uint16_t PppToEther (uint16_t protocol);
+
+  /**
+   * \brief Ethernet to PPP protocol number mapping
+   * \param protocol An Ethernet protocol number
+   * \return The corresponding PPP protocol number
+   */
+  static uint16_t EtherToPpp (uint16_t protocol);
+};
+
+} // namespace ns3
+
+#endif /* ISL_NET_DEVICE_H */
diff --git a/model/isl-propagation-loss-model.cc b/model/isl-propagation-loss-model.cc
new file mode 100644
index 0000000..de6622b
--- /dev/null
+++ b/model/isl-propagation-loss-model.cc
@@ -0,0 +1,73 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Contributions: Timo Bingmann <timo.bingmann@student.kit.edu>
+ * Contributions: Gary Pei <guangyu.pei@boeing.com> for fixed RSS
+ * Contributions: Tom Hewer <tomhewer@mac.com> for two ray ground model
+ *                Pavel Boyko <boyko@iitp.ru> for matrix
+ */
+
+#include "isl-propagation-loss-model.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("IslPropagationLossModel");
+
+NS_OBJECT_ENSURE_REGISTERED (IslPropagationLossModel);
+
+TypeId
+IslPropagationLossModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::IslPropagationLossModel")
+    .SetParent<PropagationLossModel> ()
+    .SetGroupName ("Leo")
+    .AddConstructor<IslPropagationLossModel> ()
+  ;
+  return tid;
+}
+
+IslPropagationLossModel::IslPropagationLossModel ()
+{
+}
+
+IslPropagationLossModel::~IslPropagationLossModel ()
+{
+}
+
+double
+IslPropagationLossModel::DoCalcRxPower (double txPowerDbm,
+                                           Ptr<MobilityModel> a,
+                                           Ptr<MobilityModel> b) const
+{
+  //Vector aPos = a->GetPosition ();
+  //Vector bPos = b->GetPosition ();
+
+  // TODO perform line-earth intersection (ray tracing)
+
+  double rxc = 0;//-m_variable->GetValue ();
+  NS_LOG_DEBUG ("attenuation coefficient="<<rxc<<"Db");
+  return txPowerDbm + rxc;
+}
+
+int64_t
+IslPropagationLossModel::DoAssignStreams (int64_t stream)
+{
+  return 0;
+}
+
+};
diff --git a/model/isl-propagation-loss-model.h b/model/isl-propagation-loss-model.h
new file mode 100644
index 0000000..414cc3b
--- /dev/null
+++ b/model/isl-propagation-loss-model.h
@@ -0,0 +1,62 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2005,2006,2007 INRIA
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ * Contributions: Timo Bingmann <timo.bingmann@student.kit.edu>
+ * Contributions: Gary Pei <guangyu.pei@boeing.com> for fixed RSS
+ * Contributions: Tom Hewer <tomhewer@mac.com> for two ray ground model
+ *                Pavel Boyko <boyko@iitp.ru> for matrix
+ */
+
+#ifndef ISL_PROPAGATION_LOSS_MODEL_H
+#define ISL_PROPAGATION_LOSS_MODEL_H
+
+#include "leo-mobility-model.h"
+#include <ns3/object.h>
+#include <ns3/propagation-loss-model.h>
+
+namespace ns3 {
+
+class IslPropagationLossModel : public PropagationLossModel
+{
+public:
+  static TypeId GetTypeId (void);
+  IslPropagationLossModel ();
+  virtual ~IslPropagationLossModel ();
+private:
+  /**
+   * Returns the Rx Power taking into account only the particular
+   * PropagationLossModel.
+   *
+   * \param txPowerDbm current transmission power (in dBm)
+   * \param a the mobility model of the source
+   * \param b the mobility model of the destination
+   * \returns the reception power after adding/multiplying propagation loss (in dBm)
+   */
+  virtual double DoCalcRxPower (double txPowerDbm,
+                                Ptr<MobilityModel> a,
+                                Ptr<MobilityModel> b) const;
+  /**
+   * Subclasses must implement this; those not using random variables
+   * can return zero
+   */
+  virtual int64_t DoAssignStreams (int64_t stream);
+};
+
+}
+
+#endif /* SATELLITE_ISL_PROPAGATION_LOSS_MODEL_H */
diff --git a/model/leo-mobility-model.cc b/model/leo-mobility-model.cc
new file mode 100644
index 0000000..50c9931
--- /dev/null
+++ b/model/leo-mobility-model.cc
@@ -0,0 +1,69 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "leo-mobility-model.h"
+
+namespace ns3 {
+
+NS_LOG_COMPONENT_DEFINE ("LeoMobilityModel");
+
+NS_OBJECT_ENSURE_REGISTERED (LeoMobilityModel);
+
+TypeId
+LeoMobilityModel::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::LeoMobilityModel")
+    .SetParent<MobilityModel> ()
+    .SetGroupName ("Leo")
+    .AddConstructor<LeoMobilityModel> ()
+  ;
+  return tid;
+}
+
+LeoMobilityModel::~LeoMobilityModel ()
+{
+}
+
+Vector
+LeoMobilityModel::DoGetPosition (void) const
+{
+  // TODO
+  return Vector();
+}
+
+void
+LeoMobilityModel::DoSetPosition (const Vector &position)
+{
+  // TODO
+}
+
+Vector
+LeoMobilityModel::DoGetVelocity (void) const
+{
+  // TODO
+  return Vector();
+}
+
+int64_t
+LeoMobilityModel::DoAssignStreams (int64_t start)
+{
+  // TODO
+  return 0;
+}
+
+};
diff --git a/model/leo-mobility-model.h b/model/leo-mobility-model.h
new file mode 100644
index 0000000..cd0f4c9
--- /dev/null
+++ b/model/leo-mobility-model.h
@@ -0,0 +1,64 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2007, 2008 University of Washington
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * 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 LEO_MOBILITY_MODEL_H
+#define LEO_MOBILITY_MODEL_H
+#include "ns3/log.h"
+#include "ns3/mobility-model.h"
+
+namespace ns3 {
+
+class LeoMobilityModel : public MobilityModel {
+public:
+  static TypeId GetTypeId (void);
+  virtual ~LeoMobilityModel ();
+
+private:
+  /**
+   * \return the current position.
+   *
+   * Concrete subclasses of this base class must
+   * implement this method.
+   */
+  virtual Vector DoGetPosition (void) const;
+  /**
+   * \param position the position to set.
+   *
+   * Concrete subclasses of this base class must
+   * implement this method.
+   */
+  virtual void DoSetPosition (const Vector &position);
+  /**
+   * \return the current velocity.
+   *
+   * Concrete subclasses of this base class must
+   * implement this method.
+   */
+  virtual Vector DoGetVelocity (void) const;
+  /**
+   * The default implementation does nothing but return the passed-in
+   * parameter.  Subclasses using random variables are expected to
+   * override this.
+   * \param start  starting stream index
+   * \return the number of streams used
+   */
+  virtual int64_t DoAssignStreams (int64_t start);
+  };
+};
+
+#endif /* LEO_MOBILITY_MODEL_H */
diff --git a/model/leo.cc b/model/leo.cc
new file mode 100644
index 0000000..3c44b06
--- /dev/null
+++ b/model/leo.cc
@@ -0,0 +1,11 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "leo.h"
+
+namespace ns3 {
+
+/* ... */
+
+
+}
+
diff --git a/model/leo.h b/model/leo.h
new file mode 100644
index 0000000..f9163d8
--- /dev/null
+++ b/model/leo.h
@@ -0,0 +1,12 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+#ifndef LEO_H
+#define LEO_H
+
+namespace ns3 {
+
+/* ... */
+
+}
+
+#endif /* LEO_H */
+
diff --git a/test/leo-test-suite.cc b/test/leo-test-suite.cc
new file mode 100644
index 0000000..595270b
--- /dev/null
+++ b/test/leo-test-suite.cc
@@ -0,0 +1,68 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+// Include a header file from your module to test.
+#include "ns3/leo.h"
+
+// An essential include is test.h
+#include "ns3/test.h"
+
+// Do not put your test classes in namespace ns3.  You may find it useful
+// to use the using directive to access the ns3 namespace directly
+using namespace ns3;
+
+// This is an example TestCase.
+class LeoTestCase1 : public TestCase
+{
+public:
+  LeoTestCase1 ();
+  virtual ~LeoTestCase1 ();
+
+private:
+  virtual void DoRun (void);
+};
+
+// Add some help text to this case to describe what it is intended to test
+LeoTestCase1::LeoTestCase1 ()
+  : TestCase ("Leo test case (does nothing)")
+{
+}
+
+// This destructor does nothing but we include it as a reminder that
+// the test case should clean up after itself
+LeoTestCase1::~LeoTestCase1 ()
+{
+}
+
+//
+// This method is the pure virtual method from class TestCase that every
+// TestCase must implement
+//
+void
+LeoTestCase1::DoRun (void)
+{
+  // A wide variety of test macros are available in src/core/test.h
+  NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
+  // Use this one for floating point comparisons
+  NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
+}
+
+// The TestSuite class names the TestSuite, identifies what type of TestSuite,
+// and enables the TestCases to be run.  Typically, only the constructor for
+// this class must be defined
+//
+class LeoTestSuite : public TestSuite
+{
+public:
+  LeoTestSuite ();
+};
+
+LeoTestSuite::LeoTestSuite ()
+  : TestSuite ("leo", UNIT)
+{
+  // TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER
+  AddTestCase (new LeoTestCase1, TestCase::QUICK);
+}
+
+// Do not forget to allocate an instance of this TestSuite
+static LeoTestSuite leoTestSuite;
+
diff --git a/wscript b/wscript
new file mode 100644
index 0000000..11f9c7e
--- /dev/null
+++ b/wscript
@@ -0,0 +1,42 @@
+# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+# def options(opt):
+#     pass
+
+# def configure(conf):
+#     conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H')
+
+def build(bld):
+    module = bld.create_ns3_module('leo', ['core','internet', 'propagation', 'stats', 'traffic', 'flow-monitor', 'applications'])
+    module.source = [
+        'model/leo.cc',
+        'model/isl-net-device.cc',
+        'model/isl-channel.cc',
+        'model/isl-propagation-loss-model.cc',
+        'model/leo-mobility-model.cc',
+        'helper/leo-helper.cc',
+        'helper/isl-helper.cc',
+        ]
+
+    module_test = bld.create_ns3_module_test_library('leo')
+    module_test.source = [
+        'test/leo-test-suite.cc',
+        ]
+
+    headers = bld(features='ns3header')
+    headers.module = 'leo'
+    headers.source = [
+        'model/leo.h',
+        'model/isl-net-device.h',
+        'model/isl-channel.h',
+        'model/isl-propagation-loss-model.h',
+        'model/leo-mobility-model.h',
+        'helper/leo-helper.h',
+        'helper/isl-helper.h',
+        ]
+
+    if bld.env.ENABLE_EXAMPLES:
+        bld.recurse('examples')
+
+    # bld.ns3_python_bindings()
+