Adding more components to CCNx stack

diff --git a/model/ccnx-interface.cc b/model/ccnx-face.cc
similarity index 61%
rename from model/ccnx-interface.cc
rename to model/ccnx-face.cc
index aca2dcd..27483b0 100644
--- a/model/ccnx-interface.cc
+++ b/model/ccnx-face.cc
@@ -19,7 +19,7 @@
  *
  */
 
-#include "ccnx-interface.h"
+#include "ccnx-face.h"
 
 #include "ns3/ccnx-address.h"
 #include "ns3/ccnx-l3-protocol.h"
@@ -29,27 +29,27 @@
 #include "ns3/node.h"
 #include "ns3/pointer.h"
 
-NS_LOG_COMPONENT_DEFINE ("CcnxInterface");
+NS_LOG_COMPONENT_DEFINE ("CcnxFace");
 
 namespace ns3 {
 
-NS_OBJECT_ENSURE_REGISTERED (CcnxInterface);
+NS_OBJECT_ENSURE_REGISTERED (CcnxFace);
 
 TypeId 
-CcnxInterface::GetTypeId (void)
+CcnxFace::GetTypeId (void)
 {
-  static TypeId tid = TypeId ("ns3::CcnxInterface")
+  static TypeId tid = TypeId ("ns3::CcnxFace")
     .SetParent<Object> ()
   ;
   return tid;
 }
 
 /** 
- * By default, Ccnx interface are created in the "down" state
+ * By default, Ccnx face are created in the "down" state
  *  with no IP addresses.  Before becoming useable, the user must 
  * invoke SetUp on them once an Ccnx address and mask have been set.
  */
-CcnxInterface::CcnxInterface () 
+CcnxFace::CcnxFace () 
   : m_ifup (false),
     m_metric (1),
     m_node (0), 
@@ -58,13 +58,13 @@
   NS_LOG_FUNCTION (this);
 }
 
-CcnxInterface::~CcnxInterface ()
+CcnxFace::~CcnxFace ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
 
 void
-CcnxInterface::DoDispose (void)
+CcnxFace::DoDispose (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_node = 0;
@@ -73,93 +73,93 @@
 }
 
 void 
-CcnxInterface::SetNode (Ptr<Node> node)
+CcnxFace::SetNode (Ptr<Node> node)
 {
   m_node = node;
 }
 
 void 
-CcnxInterface::SetDevice (Ptr<NetDevice> device)
+CcnxFace::SetDevice (Ptr<NetDevice> device)
 {
   m_device = device;
 }
 
 Ptr<NetDevice>
-CcnxInterface::GetDevice (void) const
+CcnxFace::GetDevice (void) const
 {
   return m_device;
 }
 
 void
-CcnxInterface::SetMetric (uint16_t metric)
+CcnxFace::SetMetric (uint16_t metric)
 {
   NS_LOG_FUNCTION (metric);
   m_metric = metric;
 }
 
 uint16_t
-CcnxInterface::GetMetric (void) const
+CcnxFace::GetMetric (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return m_metric;
 }
 
 /**
- * These are interface states and may be distinct from 
+ * These are face states and may be distinct from 
  * NetDevice states, such as found in real implementations
- * (where the device may be down but interface state is still up).
+ * (where the device may be down but face state is still up).
  */
 bool 
-CcnxInterface::IsUp (void) const
+CcnxFace::IsUp (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return m_ifup;
 }
 
 bool 
-CcnxInterface::IsDown (void) const
+CcnxFace::IsDown (void) const
 {
   NS_LOG_FUNCTION_NOARGS ();
   return !m_ifup;
 }
 
 void 
-CcnxInterface::SetUp (void)
+CcnxFace::SetUp (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_ifup = true;
 }
 
 void 
-CcnxInterface::SetDown (void)
+CcnxFace::SetDown (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_ifup = false;
 }
 
 void
-CcnxInterface::Send (Ptr<Packet> p)
+CcnxFace::Send (Ptr<Packet> packet)
 {
-  NS_LOG_FUNCTION (*p);
+  NS_ASSERT_MSG (packet->GetSize () <= GetDevice ()->GetMtu (), 
+                 "Packet size " << packet->GetSize () << " exceeds device MTU "
+                                << GetDevice ()->GetMtu ()
+                                << " for Ccnx; fragmentation not supported");
+
+  NS_LOG_FUNCTION (*packet);
   if (!IsUp ())
     {
       return;
     }
 
-  // Check if Local Delivery
-  // if (DynamicCast<LoopbackNetDevice> (m_device))
-  //   {
-  //     // XXX additional checks needed here (such as whether multicast
-  //     // goes to loopback)?
-  //     m_device->Send (p, m_device->GetBroadcast (), 
-  //                     CcnxL3Protocol::PROT_NUMBER);
-  //     return;
-  //   }
-
-  NS_LOG_LOGIC ("Doesn't need ARP");
-  m_device->Send (p, m_device->GetBroadcast (), 
+  m_device->Send (packet, m_device->GetBroadcast (), 
                   CcnxL3Protocol::PROT_NUMBER);
 }
 
+std::ostream& operator<< (std::ostream& os, CcnxFace const& face)
+{
+  os << "dev=" << face.GetDevice ()->GetIfIndex ();
+  return os;
+}
+
 }; // namespace ns3
 
diff --git a/model/ccnx-interface.h b/model/ccnx-face.h
similarity index 62%
rename from model/ccnx-interface.h
rename to model/ccnx-face.h
index f82c3d5..769f938 100644
--- a/model/ccnx-interface.h
+++ b/model/ccnx-face.h
@@ -17,10 +17,12 @@
  *
  * Authors: 
  */
-#ifndef CCNX_INTERFACE_H
-#define CCNX_INTERFACE_H
+#ifndef CCNX_FACE_H
+#define CCNX_FACE_H
 
 #include <list>
+#include <ostream>
+
 #include "ns3/ptr.h"
 #include "ns3/object.h"
 
@@ -31,79 +33,79 @@
 class Node;
 
 /**
- * \brief The Ccnx representation of a network interface
+ * \brief The Ccnx representation of a network face
  *
  * This class roughly corresponds to the struct in_device
  * of Linux; the main purpose is to provide address-family
- * specific information (addresses) about an interface.
+ * specific information (addresses) about an face.
  *
- * By default, Ccnx interface are created in the "down" state
+ * By default, Ccnx face are created in the "down" state
  * no IP addresses.  Before becoming useable, the user must 
  * add an address of some type and invoke Setup on them.
  */
-class CcnxInterface  : public Object
+class CcnxFace  : public Object
 {
 public:
   static TypeId GetTypeId (void);
 
-  CcnxInterface ();
-  virtual ~CcnxInterface();
+  CcnxFace ();
+  virtual ~CcnxFace();
 
-  void SetNode (Ptr<Node> node); 
-  void SetDevice (Ptr<NetDevice> device);
+  virtual void SetNode (Ptr<Node> node); 
+  virtual void SetDevice (Ptr<NetDevice> device);
 
   /**
    * \returns the underlying NetDevice. This method cannot return zero.
    */
-  Ptr<NetDevice> GetDevice (void) const;
+  virtual Ptr<NetDevice> GetDevice (void) const;
 
   /**
-   * \param metric configured routing metric (cost) of this interface
+   * \param metric configured routing metric (cost) of this face
    *
    * Note:  This is synonymous to the Metric value that ifconfig prints
    * out.  It is used by ns-3 global routing, but other routing daemons
    * choose to ignore it. 
    */
-  void SetMetric (uint16_t metric);
+  virtual void SetMetric (uint16_t metric);
 
   /**
-   * \returns configured routing metric (cost) of this interface
+   * \returns configured routing metric (cost) of this face
    *
    * Note:  This is synonymous to the Metric value that ifconfig prints
    * out.  It is used by ns-3 global routing, but other routing daemons 
    * may choose to ignore it. 
    */
-  uint16_t GetMetric (void) const;
+  virtual uint16_t GetMetric (void) const;
 
   /**
-   * These are IP interface states and may be distinct from 
+   * These are IP face states and may be distinct from 
    * NetDevice states, such as found in real implementations
-   * (where the device may be down but IP interface state is still up).
+   * (where the device may be down but IP face state is still up).
    */
   /**
-   * \returns true if this interface is enabled, false otherwise.
+   * \returns true if this face is enabled, false otherwise.
    */
-  bool IsUp (void) const;
+  virtual bool IsUp (void) const;
 
   /**
-   * \returns true if this interface is disabled, false otherwise.
+   * \returns true if this face is disabled, false otherwise.
    */
-  bool IsDown (void) const;
+  virtual bool IsDown (void) const;
 
   /**
-   * Enable this interface
+   * Enable this face
    */
-  void SetUp (void);
+  virtual void SetUp (void);
 
   /**
-   * Disable this interface
+   * Disable this face
    */
-  void SetDown (void);
+  virtual void SetDown (void);
 
   /**
    * \param p packet to send
    */ 
-  void Send (Ptr<Packet> p);
+  virtual void Send (Ptr<Packet> p);
 
 protected:
   virtual void DoDispose (void);
@@ -115,6 +117,8 @@
   Ptr<NetDevice> m_device;
 };
 
+std::ostream& operator<< (std::ostream& os, CcnxFace const& face);
+
 } // namespace ns3
 
-#endif
+#endif //CCNX_FACE_H
diff --git a/model/ccnx-forwarding-protocol.cc b/model/ccnx-forwarding-protocol.cc
new file mode 100644
index 0000000..b7e5a11
--- /dev/null
+++ b/model/ccnx-forwarding-protocol.cc
@@ -0,0 +1,42 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 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/assert.h"
+
+#include "ccnx-route.h"
+#include "ccnx-forwarding-protocol.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxForwardingProtocol);
+
+TypeId CcnxForwardingProtocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxForwardingProtocol")
+    .SetParent<Object> ()
+  ;
+  return tid;
+}
+
+void
+CcnxForwardingProtocol::SetCcnx (Ptr<Ccnx> ccnx)
+{
+  m_ccnx = ccnx;
+}
+
+} //namespace ns3
diff --git a/model/ccnx-forwarding-protocol.h b/model/ccnx-forwarding-protocol.h
new file mode 100644
index 0000000..e6d2586
--- /dev/null
+++ b/model/ccnx-forwarding-protocol.h
@@ -0,0 +1,144 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 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 CCNX_FORWARDING_PROTOCOL_H
+#define CCNX_FORWARDING_PROTOCOL_H
+
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/object.h"
+#include "ns3/socket.h"
+#include "ccnx-header.h"
+#include "ns3/ccnx-interface-address.h"
+#include "ccnx.h"
+#include "ns3/output-stream-wrapper.h"
+
+namespace ns3 {
+
+class CcnxRoute;
+class CcnxFace;
+
+/**
+ * \ingroup internet 
+ * \defgroup ccnxForwarding CcnxForwardingProtocol 
+ */
+/**
+ * \ingroup ccnxForwarding
+ * \brief Abstract base class for Ccnx forwarding protocols. 
+ * 
+ * Defines two virtual functions for packet forwarding and forwarding.  The first, 
+ * RouteOutput(), is used for locally originated packets, and the second,
+ * RouteInput(), is used for forwarding and/or delivering received packets. 
+ * Also defines the signatures of four callbacks used in RouteInput().
+ *
+ */
+class CcnxForwardingProtocol : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  typedef Callback<void, Ptr<const Packet>, Ptr<CcnxRoute> > SendCallback;
+  typedef Callback<void, Ptr<const Packet>, Socket::SocketErrno > ErrorCallback;
+
+  /**
+   * \brief Query forwarding cache for an existing route, for an outbound packet
+  //  *
+  //  * This lookup is used by transport protocols.  It does not cause any
+  //  * packet to be forwarded, and is synchronous.  Can be used for
+  //  * multicast or unicast.  The Linux equivalent is ip_route_output()
+  //  *
+  //  * \param p packet to be routed.  Note that this method may modify the packet.
+  //  *          Callers may also pass in a null pointer. 
+  //  * \param header input parameter (used to form key to search for the route)
+  //  * \param oif Output interface Netdevice.  May be zero, or may be bound via
+  //  *            socket options to a particular output interface.
+  //  * \param sockerr Output parameter; socket errno 
+  //  *
+  //  * \returns a code that indicates what happened in the lookup
+  //  */
+  // virtual Ptr<CcnxRoute> RouteOutput (Ptr<Packet> p, const CcnxHeader &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr) = 0;
+
+  /**
+   * \brief Route an input packet (to be forwarded or locally delivered)
+   *
+   * This lookup is used in the forwarding process.  The packet is
+   * handed over to the CcnxForwardingProtocol, and will get forwarded onward
+   * by one of the callbacks.  The Linux equivalent is ip_route_input().
+   * There are four valid outcomes, and a matching callbacks to handle each.
+   *
+   * \param p received packet
+   * \param header input parameter used to form a search key for a route
+   * \param iface Pointer to ingress face
+   * \param ucb Callback for the case in which the packet is to be forwarded
+   * \param ecb Callback to call if there is an error in forwarding
+   * \returns true if the CcnxForwardingProtocol takes responsibility for 
+   *          forwarding or delivering the packet, false otherwise
+   */ 
+  virtual bool RouteInput  (Ptr<const Packet> p, Ptr<const CcnxFace> iface, 
+                            SendCallback ucb, ErrorCallback ecb) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   *
+   * Protocols are expected to implement this method to be notified of the state change of
+   * an interface in a node.
+   */
+  virtual void NotifyInterfaceUp (uint32_t interface) = 0;
+  /**
+   * \param interface the index of the interface we are being notified about
+   *
+   * Protocols are expected to implement this method to be notified of the state change of
+   * an interface in a node.
+   */
+  virtual void NotifyInterfaceDown (uint32_t interface) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   * \param address a new address being added to an interface
+   *
+   * Protocols are expected to implement this method to be notified whenever
+   * a new address is added to an interface. Typically used to add a 'network route' on an
+   * interface. Can be invoked on an up or down interface.
+   */
+  virtual void NotifyAddAddress (uint32_t interface, CcnxInterfaceAddress address) = 0;
+
+  /**
+   * \param interface the index of the interface we are being notified about
+   * \param address a new address being added to an interface
+   *
+   * Protocols are expected to implement this method to be notified whenever
+   * a new address is removed from an interface. Typically used to remove the 'network route' of an
+   * interface. Can be invoked on an up or down interface.
+   */
+  virtual void NotifyRemoveAddress (uint32_t interface, CcnxInterfaceAddress address) = 0;
+
+  /**
+   * \param ccnx the ccnx object this forwarding protocol is being associated with
+   * 
+   * Typically, invoked directly or indirectly from ns3::Ccnx::SetForwardingProtocol
+   */
+  virtual void SetCcnx (Ptr<Ccnx> ccnx);
+
+  virtual void PrintForwardingTable (Ptr<OutputStreamWrapper> stream) const = 0;
+
+protected:
+  Ptr<Ccnx> m_ccnx;
+};
+
+} //namespace ns3
+
+#endif /* CCNX_FORWARDING_PROTOCOL_H */
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index bf1230c..bbb5853 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -15,7 +15,7 @@
 // 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>
+// Author: 
 //
 
 #include "ns3/packet.h"
@@ -24,16 +24,13 @@
 #include "ns3/ccnx-address.h"
 #include "ns3/ccnx-route.h"
 #include "ns3/node.h"
-#include "ns3/socket.h"
 #include "ns3/net-device.h"
 #include "ns3/uinteger.h"
 #include "ns3/trace-source-accessor.h"
 #include "ns3/object-vector.h"
-#include "ns3/ccnx-header.h"
 #include "ns3/boolean.h"
 //#include "ns3/ccnx-routing-table-entry.h"
 
-#include "arp-l3-protocol.h"
 #include "ccnx-l3-protocol.h"
 #include "ccnx-interface.h"
 
@@ -70,7 +67,6 @@
 }
 
 CcnxL3Protocol::CcnxL3Protocol()
-  : m_identification (0)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -84,8 +80,6 @@
 CcnxL3Protocol::SetNode (Ptr<Node> node)
 {
   m_node = node;
-  // Add a LoopbackNetDevice if needed, and an CcnxInterface on top of it
-  SetupLoopback ();
 }
 
 /*
@@ -108,443 +102,156 @@
   Object::NotifyNewAggregate ();
 }
 
-// void 
-// CcnxL3Protocol::SetRoutingProtocol (Ptr<CcnxRoutingProtocol> routingProtocol)
-// {
-//   NS_LOG_FUNCTION (this);
-//   m_routingProtocol = routingProtocol;
-//   m_routingProtocol->SetCcnx (this);
-// }
+void
+CcnxL3Protocol::SetForwardingProtocol (Ptr<CcnxForwardingProtocol> forwardingProtocol)
+{
+  NS_LOG_FUNCTION (this);
+  m_forwardingProtocol = forwardingProtocol;
+  m_forwardingProtocol->SetCcnx (this);
+}
 
-
-// Ptr<CcnxRoutingProtocol> 
-// CcnxL3Protocol::GetRoutingProtocol (void) const
-// {
-//   return m_routingProtocol;
-// }
+Ptr<CcnxForwardingProtocol>
+CcnxL3Protocol::GetForwardingProtocol (void) const
+{
+  return m_forwardingProtocol;
+}
 
 void 
 CcnxL3Protocol::DoDispose (void)
 {
   NS_LOG_FUNCTION (this);
 
-  for (CcnxInterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
+  for (CcnxInterfaceList::iterator i = m_faces.begin (); i != m_faces.end (); ++i)
     {
       *i = 0;
     }
-  m_interfaces.clear ();
+  m_faces.clear ();
   m_node = 0;
-  // m_routingProtocol = 0;
+  // m_forwardingProtocol = 0;
   Object::DoDispose ();
 }
 
 uint32_t 
-CcnxL3Protocol::AddInterface (Ptr<NetDevice> device)
+CcnxL3Protocol::AddFace (Ptr<CcnxFace> face)
 {
-  NS_LOG_FUNCTION (this << &device);
+  NS_LOG_FUNCTION (this << *face);
 
-  Ptr<Node> node = GetObject<Node> ();
-  node->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::Receive, this), 
-                                 CcnxL3Protocol::PROT_NUMBER, device, true);
+  // Ptr<Node> node = GetObject<Node> (); ///< \todo not sure why this thing should be called...
+  face->setNode (m_node);
 
-  // ccnx doesn't need arp protocol to run. Everything is broadcast!
-  // node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
-  //                                ArpL3Protocol::PROT_NUMBER, device, true);
+  if (face->GetDevice() != 0)
+    {
+      m_node->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::Receive, this), 
+                                       CcnxL3Protocol::PROT_NUMBER, face->GetDevice(), true/*promiscuous mode*/);
+    }
 
-  Ptr<CcnxInterface> interface = CreateObject<CcnxInterface> ();
-  interface->SetNode (m_node);
-  interface->SetDevice (device);
-  // interface->SetForwarding (m_ipForward);
-  return AddCcnxInterface (interface);
-}
-
-uint32_t 
-CcnxL3Protocol::AddCcnxInterface (Ptr<CcnxInterface>interface)
-{
-  NS_LOG_FUNCTION (this << interface);
-  uint32_t index = m_interfaces.size ();
-  m_interfaces.push_back (interface);
+  uint32_t index = m_faces.size ();
+  m_faces.push_back (interface);
   return index;
 }
 
+
 Ptr<CcnxInterface>
-CcnxL3Protocol::GetInterface (uint32_t index) const
+CcnxL3Protocol::GetFace (uint32_t index) const
 {
-  if (index < m_interfaces.size ())
+  if (index < m_faces.size ())
     {
-      return m_interfaces[index];
+      return m_faces[index];
     }
   return 0;
 }
 
 uint32_t 
-CcnxL3Protocol::GetNInterfaces (void) const
+CcnxL3Protocol::GetNFaces (void) const
 {
-  return m_interfaces.size ();
+  return m_faces.size ();
 }
 
-int32_t 
-CcnxL3Protocol::GetInterfaceForDevice (
-  Ptr<const NetDevice> device) const
+Ptr<CcnxFace>
+GetFaceForDevice (Ptr<const NetDevice> device) const
 {
-  int32_t interface = 0;
-  for (CcnxInterfaceList::const_iterator i = m_interfaces.begin (); 
-       i != m_interfaces.end (); 
-       i++, interface++)
+  for (CcnxInterfaceList::const_iterator i = m_faces.begin (); 
+       i != m_faces.end (); 
+       i++, face++)
     {
       if ((*i)->GetDevice () == device)
         {
-          return interface;
+          return *i;
         }
     }
 
-  return -1;
+  NS_ASSERT_MSG (false "Should never get to this place" );
+  return 0;
 }
 
+// Callback from lower layer
 void 
 CcnxL3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
                           const Address &to, NetDevice::PacketType packetType)
 {
   NS_LOG_FUNCTION (this << &device << p << protocol <<  from);
 
-  NS_LOG_LOGIC ("Packet from " << from << " received on node " << 
-                m_node->GetId ());
+  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<  m_node->GetId ());
 
   uint32_t interface = 0;
   Ptr<Packet> packet = p->Copy ();
 
-  Ptr<CcnxInterface> ccnxInterface;
-  for (CcnxInterfaceList::const_iterator i = m_interfaces.begin (); 
-       i != m_interfaces.end (); 
-       i++, interface++)
-    {
-      ccnxInterface = *i;
-      if (ccnxInterface->GetDevice () == device)
-        {
-          if (ccnxInterface->IsUp ())
-            {
-              m_rxTrace (packet, m_node->GetObject<Ccnx> (), interface);
-              break;
-            }
-          else
-            {
-              NS_LOG_LOGIC ("Dropping received packet -- interface is down");
-              CcnxHeader ipHeader;
-              packet->RemoveHeader (ipHeader);
-              m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), interface);
-              return;
-            }
-        }
-    }
+  Ptr<CcnxFace> ccnxFace = GetFaceFromDevice (device);
 
-  CcnxHeader ipHeader;
-  if (Node::ChecksumEnabled ())
-    {
-      ipHeader.EnableChecksum ();
-    }
-  packet->RemoveHeader (ipHeader);
+  Receive (ccnxFace, p);
+}
 
-  // Trim any residual frame padding from underlying devices
-  if (ipHeader.GetPayloadSize () < packet->GetSize ())
+// Callback from higher level
+void Receive (Ptr<CcnxFace> incomingFace, Ptr<const Packet> p)
+{
+  if ( incomingFace->IsUp ())
     {
-      packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
-    }
-
-  if (!ipHeader.IsChecksumOk ()) 
-    {
-      NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
-      m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject<Ccnx> (), interface);
+      NS_LOG_LOGIC ("Dropping received packet -- interface is down");
+      m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), incomingFace);
       return;
     }
-
-  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
-    {
-      NS_LOG_LOGIC ("Forwarding to raw socket"); 
-      Ptr<CcnxRawSocketImpl> socket = *i;
-      socket->ForwardUp (packet, ipHeader, ccnxInterface);
-    }
+  
+  m_rxTrace (packet, m_node->GetObject<Ccnx> (), incomingFace);
 
   NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
-  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
-                                      MakeCallback (&CcnxL3Protocol::IpForward, this),
-                                      MakeCallback (&CcnxL3Protocol::IpMulticastForward, this),
-                                      MakeCallback (&CcnxL3Protocol::LocalDeliver, this),
+  if (!m_routingProtocol->RouteInput (packet, incomingFace,
+                                      MakeCallback (&CcnxL3Protocol::Send, this),
                                       MakeCallback (&CcnxL3Protocol::RouteInputError, this)
                                       ))
     {
       NS_LOG_WARN ("No route found for forwarding packet.  Drop.");
-      m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), interface);
+      m_dropTrace (packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), incomingFace);
     }
-
-
-}
-
-// void 
-// CcnxL3Protocol::SendWithHeader (Ptr<Packet> packet, 
-//                                 CcnxHeader ipHeader,
-//                                 Ptr<CcnxRoute> route)
-// {
-//   NS_LOG_FUNCTION (this << packet << ipHeader << route);
-//   SendRealOut (route, packet, ipHeader);
-// }
-
-void 
-CcnxL3Protocol::Send (Ptr<Packet> packet, 
-                      Ptr<CcnxRoute> route)
-{
-  NS_LOG_FUNCTION (this << packet << route);
-
-  // CcnxHeader ipHeader;
-  // bool mayFragment = true;
-  // uint8_t ttl = m_defaultTtl;
-  // SocketIpTtlTag tag;
-  // bool found = packet->RemovePacketTag (tag);
-  // if (found)
-  //   {
-  //     ttl = tag.GetTtl ();
-  //   }
-
-  // // Handle a few cases:
-  // // 1) packet is destined to limited broadcast address
-  // // 2) packet is destined to a subnet-directed broadcast address
-  // // 3) packet is not broadcast, and is passed in with a route entry
-  // // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
-  // // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
-
-  // // 1) packet is destined to limited broadcast address or link-local multicast address
-  // if (destination.IsBroadcast () || destination.IsLocalMulticast ())
-  //   {
-  //     NS_LOG_LOGIC ("CcnxL3Protocol::Send case 1:  limited broadcast");
-  //     ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
-  //     uint32_t ifaceIndex = 0;
-  //     for (CcnxInterfaceList::iterator ifaceIter = m_interfaces.begin ();
-  //          ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
-  //       {
-  //         Ptr<CcnxInterface> outInterface = *ifaceIter;
-  //         Ptr<Packet> packetCopy = packet->Copy ();
-
-  //         NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ());
-
-  //         m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
-  //         packetCopy->AddHeader (ipHeader);
-  //         m_txTrace (packetCopy, m_node->GetObject<Ccnx> (), ifaceIndex);
-  //         outInterface->Send (packetCopy, destination);
-  //       }
-  //     return;
-  //   }
-
-  // // 2) check: packet is destined to a subnet-directed broadcast address
-  // uint32_t ifaceIndex = 0;
-  // for (CcnxInterfaceList::iterator ifaceIter = m_interfaces.begin ();
-  //      ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
-  //   {
-  //     Ptr<CcnxInterface> outInterface = *ifaceIter;
-  //     for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
-  //       {
-  //         CcnxInterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
-  //         NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
-  //         if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) && 
-  //             destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ())   )
-  //           {
-  //             NS_LOG_LOGIC ("CcnxL3Protocol::Send case 2:  subnet directed bcast to " << ifAddr.GetLocal ());
-  //             ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
-  //             Ptr<Packet> packetCopy = packet->Copy ();
-  //             m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
-  //             packetCopy->AddHeader (ipHeader);
-  //             m_txTrace (packetCopy, m_node->GetObject<Ccnx> (), ifaceIndex);
-  //             outInterface->Send (packetCopy, destination);
-  //             return;
-  //           }
-  //       }
-  //   }
-
-  // // 3) packet is not broadcast, and is passed in with a route entry
-  // //    with a valid CcnxAddress as the gateway
-  // if (route && route->GetGateway () != CcnxAddress ())
-  //   {
-  //     NS_LOG_LOGIC ("CcnxL3Protocol::Send case 3:  passed in with route");
-  //     ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
-  //     int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
-  //     m_sendOutgoingTrace (ipHeader, packet, interface);
-  //     SendRealOut (route, packet->Copy (), ipHeader);
-  //     return; 
-  //   } 
-  // // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
-  // if (route && route->GetGateway () == CcnxAddress ())
-  //   {
-  //     // This could arise because the synchronous RouteOutput() call
-  //     // returned to the transport protocol with a source address but
-  //     // there was no next hop available yet (since a route may need
-  //     // to be queried).
-  //     NS_FATAL_ERROR ("CcnxL3Protocol::Send case 4: This case not yet implemented");
-  //   }
-  // // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
-  // NS_LOG_LOGIC ("CcnxL3Protocol::Send case 5:  passed in with no route " << destination);
-  // Socket::SocketErrno errno_; 
-  // Ptr<NetDevice> oif (0); // unused for now
-  // ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
-  // Ptr<CcnxRoute> newRoute;
-  // if (m_routingProtocol != 0)
-  //   {
-  //     newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
-  //   }
-  // else
-  //   {
-  //     NS_LOG_ERROR ("CcnxL3Protocol::Send: m_routingProtocol == 0");
-  //   }
-  // if (newRoute)
-  //   {
-  //     int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
-  //     m_sendOutgoingTrace (ipHeader, packet, interface);
-  //     SendRealOut (newRoute, packet->Copy (), ipHeader);
-  //   }
-  // else
-  //   {
-  //     NS_LOG_WARN ("No route to host.  Drop.");
-  //     m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), 0);
-  //   }
 }
 
 
 void
-CcnxL3Protocol::SendRealOut (Ptr<CcnxRoute> route,
-                             Ptr<Packet> packet,
-                             CcnxHeader const &ipHeader)
+CcnxL3Protocol::Send (Ptr<Packet> packet, Ptr<CcnxRoute> route)
 {
-  NS_LOG_FUNCTION (this << packet << &ipHeader);
+  NS_LOG_FUNCTION (this << "packet: " << packet << ", route: "<< route);
 
-  // if (route == 0)
-  //   {
-  //     NS_LOG_WARN ("No route to host.  Drop.");
-  //     m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), 0);
-  //     return;
-  //   }
-  // packet->AddHeader (ipHeader);
-  // Ptr<NetDevice> outDev = route->GetOutputDevice ();
-  // int32_t interface = GetInterfaceForDevice (outDev);
-  // NS_ASSERT (interface >= 0);
-  // Ptr<CcnxInterface> outInterface = GetInterface (interface);
-  // NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ccnxInterfaceIndex " << interface);
+  if (route == 0)
+    {
+      NS_LOG_WARN ("No route to host.  Drop.");
+      m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), 0);
+      return;
+    }
+  Ptr<CcnxFace> outFace = route->GetOutputFace ();
 
-  // NS_ASSERT_MSG (packet->GetSize () <= outInterface->GetDevice ()->GetMtu (), 
-  //                "Packet size " << packet->GetSize () << " exceeds device MTU "
-  //                               << outInterface->GetDevice ()->GetMtu ()
-  //                               << " for Ccnx; fragmentation not supported");
-  // if (!route->GetGateway ().IsEqual (CcnxAddress ("0.0.0.0"))) 
-  //   {
-  //     if (outInterface->IsUp ())
-  //       {
-  //         NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
-  //         m_txTrace (packet, m_node->GetObject<Ccnx> (), interface);
-  //         outInterface->Send (packet, route->GetGateway ());
-  //       }
-  //     else
-  //       {
-  //         NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
-  //         CcnxHeader ipHeader;
-  //         packet->RemoveHeader (ipHeader);
-  //         m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), interface);
-  //       }
-  //   } 
-  // else 
-  //   {
-  //     if (outInterface->IsUp ())
-  //       {
-  //         NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
-  //         m_txTrace (packet, m_node->GetObject<Ccnx> (), interface);
-  //         outInterface->Send (packet, ipHeader.GetDestination ());
-  //       }
-  //     else
-  //       {
-  //         NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
-  //         CcnxHeader ipHeader;
-  //         packet->RemoveHeader (ipHeader);
-  //         m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), interface);
-  //       }
-  //   }
+  if (outFace->IsUp ())
+    {
+      NS_LOG_LOGIC ("Sending via face " << *outFace);
+      m_txTrace (packet, m_node->GetObject<Ccnx> (), outFace);
+      outFace->Send (packet);
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << *outFace);
+      m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), outFace);
+    }
 }
 
 
-// This function analogous to Linux ip_forward()
-// void
-// CcnxL3Protocol::IpForward (Ptr<CcnxRoute> rtentry, Ptr<const Packet> p, const CcnxHeader &header)
-// {
-//   NS_LOG_FUNCTION (this << rtentry << p << header);
-//   NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
-//   // Forwarding
-//   CcnxHeader ipHeader = header;
-//   Ptr<Packet> packet = p->Copy ();
-//   int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
-//   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
-//   if (ipHeader.GetTtl () == 0)
-//     {
-//       // Do not reply to ICMP or to multicast/broadcast IP address 
-//       if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER && 
-//           ipHeader.GetDestination ().IsBroadcast () == false &&
-//           ipHeader.GetDestination ().IsMulticast () == false)
-//         {
-//           Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
-//           icmp->SendTimeExceededTtl (ipHeader, packet);
-//         }
-//       NS_LOG_WARN ("TTL exceeded.  Drop.");
-//       m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ccnx> (), interface);
-//       return;
-//     }
-//   m_unicastForwardTrace (ipHeader, packet, interface);
-//   SendRealOut (rtentry, packet, ipHeader);
-// }
-
-// Will be called from CcnxRoutingProtocol if prefix is locally registered
-// Local interest will be satisfied inside CcnxInterface::Send call
-
-void
-CcnxL3Protocol::LocalDeliver (Ptr<const Packet> packet, CcnxHeader const&ip, uint32_t iif)
-{
-  NS_LOG_FUNCTION (this << packet << &ip);
-  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
-
-//   m_localDeliverTrace (ip, packet, iif);
-
-//   Ptr<CcnxL4Protocol> protocol = GetProtocol (ip.GetProtocol ());
-//   if (protocol != 0)
-//     {
-//       // we need to make a copy in the unlikely event we hit the
-//       // RX_ENDPOINT_UNREACH codepath
-//       Ptr<Packet> copy = p->Copy ();
-//       enum CcnxL4Protocol::RxStatus status = 
-//         protocol->Receive (p, ip, GetInterface (iif));
-//       switch (status) {
-//         case CcnxL4Protocol::RX_OK:
-//         // fall through
-//         case CcnxL4Protocol::RX_ENDPOINT_CLOSED:
-//         // fall through
-//         case CcnxL4Protocol::RX_CSUM_FAILED:
-//           break;
-//         case CcnxL4Protocol::RX_ENDPOINT_UNREACH:
-//           if (ip.GetDestination ().IsBroadcast () == true ||
-//               ip.GetDestination ().IsMulticast () == true)
-//             {
-//               break; // Do not reply to broadcast or multicast
-//             }
-//           // Another case to suppress ICMP is a subnet-directed broadcast
-//           bool subnetDirected = false;
-//           for (uint32_t i = 0; i < GetNAddresses (iif); i++)
-//             {
-//               CcnxInterfaceAddress addr = GetAddress (iif, i);
-//               if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination ().CombineMask (addr.GetMask ()) &&
-//                   ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
-//                 {
-//                   subnetDirected = true;
-//                 }
-s//             }
-//           if (subnetDirected == false)
-//             {
-//               GetIcmp ()->SendDestUnreachPort (ip, copy);
-//             }
-//         }
-//     }
-}
-
 void 
 CcnxL3Protocol::SetMetric (uint32_t i, uint16_t metric)
 {
@@ -600,12 +307,6 @@
     }
 }
 
-Ptr<NetDevice>
-CcnxL3Protocol::GetNetDevice (uint32_t i)
-{
-  return GetInterface (i)->GetDevice ();
-}
-
 void
 CcnxL3Protocol::RouteInputError (Ptr<const Packet> p, const CcnxHeader & ipHeader, Socket::SocketErrno sockErrno)
 {
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index d83f687..d45f0b3 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -15,7 +15,7 @@
 // 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>
+// Author: 
 //
 
 #ifndef CCNX_L3_PROTOCOL_H
@@ -34,12 +34,10 @@
 class Packet;
 class NetDevice;
 class CcnxInterface;
-// class CcnxAddress;
-// class CcnxHeader;
-// class CcnxRoutingTableEntry;
 class CcnxRoute;
 class Node;
 class Socket;
+class CcnxForwardingProtocol;
 
 
 /**
@@ -73,9 +71,10 @@
    */
   enum DropReason 
   {
-    DROP_TTL_EXPIRED = 1,   /**< Packet TTL has expired */
+    /** \todo  Fill reasons from QualNet code */
+    DROP_DUPLICATE_INTEREST=1,  /**< Duplicate Interest */
+    DROP_CONGESTION, /**< Congestion detected */
     DROP_NO_ROUTE,   /**< No route to host */
-    DROP_BAD_CHECKSUM,   /**< Bad checksum */
     DROP_INTERFACE_DOWN,   /**< Interface is down so can not send packet */
     DROP_ROUTE_ERROR,   /**< Route error */
   };
@@ -83,19 +82,13 @@
   void SetNode (Ptr<Node> node);
 
   // functions defined in base class Ccnx
-
-  // void SetRoutingProtocol (Ptr<CcnxRoutingProtocol> routingProtocol);
-  // Ptr<CcnxRoutingProtocol> GetRoutingProtocol (void) const;
-
-  // Ptr<Socket> CreateRawSocket (void);
-  // void DeleteRawSocket (Ptr<Socket> socket);
+  
+  void SetForwardingProtocol (Ptr<CcnxForwardingProtocol> forwardingProtocol);
+  Ptr<CcnxForwardingProtocol> GetForwardingProtocol (void) const;
 
   /**
    * Lower layer calls this method after calling L3Demux::Lookup
-   * The ARP subclass needs to know from which NetDevice this
-   * packet is coming to:
-   *    - implement a per-NetDevice ARP cache
-   *    - send back arp replies on the right device
+   *
    * \param device network device
    * \param p the packet
    * \param protocol lower layer protocol value
@@ -103,75 +96,62 @@
    * \param to lower layer address of the destination
    * \param packetType type of the packet (broadcast/multicast/unicast/otherhost)
    */
-  void Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol,
+  void Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol,
                  const Address &from,
                  const Address &to,
                  NetDevice::PacketType packetType);
 
   /**
+   * Actual processing of incoming CCNx packets. Also processing packets coming from local apps
+   */
+  void Receive (Ptr<CcnxFace> face, Ptr<const Packet> p);
+  
+  /**
    * \param packet packet to send
    * \param route route entry
    *
    * Higher-level layers call this method to send a packet
    * down the stack to the MAC and PHY layers.
    */
-  void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route);
+  virtual void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route);
 
-  uint32_t AddInterface (Ptr<NetDevice> device);
-  Ptr<CcnxInterface> GetInterface (uint32_t i) const;
-  uint32_t GetNInterfaces (void) const;
+  virtual uint32_t AddFace (Ptr<CcnxFace> face);
+  virtual uint32_t GetNFaces (void) const;
+  virtual Ptr<CcnxFace> GetFace (uint32_t face);
 
-  int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const;
-  // bool IsDestinationAddress (CcnxAddress address, uint32_t iif) const;
-
-  void SetMetric (uint32_t i, uint16_t metric);
-  uint16_t GetMetric (uint32_t i) const;
-  uint16_t GetMtu (uint32_t i) const;
-  bool IsUp (uint32_t i) const;
-  void SetUp (uint32_t i);
-  void SetDown (uint32_t i);
-
-  Ptr<NetDevice> GetNetDevice (uint32_t i);
+  virtual void SetMetric (uint32_t i, uint16_t metric);
+  virtual uint16_t GetMetric (uint32_t i) const;
+  virtual uint16_t GetMtu (uint32_t i) const;
+  virtual bool IsUp (uint32_t i) const;
+  virtual void SetUp (uint32_t i);
+  virtual void SetDown (uint32_t i);
 
 protected:
-
   virtual void DoDispose (void);
   /**
    * This function will notify other components connected to the node that a new stack member is now connected
    * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
    */
   virtual void NotifyNewAggregate ();
+
 private:
   // friend class CcnxL3ProtocolTestCase;
   CcnxL3Protocol(const CcnxL3Protocol &);
   CcnxL3Protocol &operator = (const CcnxL3Protocol &);
 
-  void
-  SendRealOut (Ptr<CcnxRoute> route,
-               Ptr<Packet> packet,
-               CcnxHeader const &ipHeader);
-
-  // void 
-  // IpForward (Ptr<CcnxRoute> rtentry, 
-  //            Ptr<const Packet> p, 
-  //            const CcnxHeader &header);
-
-  // void
-  // IpMulticastForward (Ptr<CcnxMulticastRoute> mrtentry, 
-  //                     Ptr<const Packet> p, 
-  //                     const CcnxHeader &header);
-
-  void LocalDeliver (Ptr<const Packet> p, CcnxHeader const&ip, uint32_t iif);
+  /**
+   * Helper function to get CcnxFace from NetDevice
+   */
+  Ptr<CcnxFace> GetFaceForDevice (Ptr<const NetDevice> device) const;
+  
   void RouteInputError (Ptr<const Packet> p, const CcnxHeader & ipHeader, Socket::SocketErrno sockErrno);
 
-  uint32_t AddCcnxInterface (Ptr<CcnxInterface> interface);
+private:
+  typedef std::vector<Ptr<CcnxFace> > CcnxFaceList;
+  CcnxFaceList m_faces;
 
-  typedef std::vector<Ptr<CcnxInterface> > CcnxInterfaceList;
-
-  CcnxInterfaceList m_interfaces;
-  uint16_t m_identification;
   Ptr<Node> m_node;
-  CcnxL4Protocol m_layer4;
+  // Ptr<CcnxForwardingProtocol> m_forwardingProtocol;
 
   TracedCallback<const CcnxHeader &, Ptr<const Packet>, uint32_t> m_sendOutgoingTrace;
   TracedCallback<const CcnxHeader &, Ptr<const Packet>, uint32_t> m_unicastForwardTrace;
@@ -182,8 +162,6 @@
   TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, uint32_t> m_rxTrace;
   // <ip-header, payload, reason, ifindex> (ifindex not valid if reason is DROP_NO_ROUTE)
   TracedCallback<const CcnxHeader &, Ptr<const Packet>, DropReason, Ptr<Ccnx>, uint32_t> m_dropTrace;
-
-  // Ptr<CcnxRoutingProtocol> m_routingProtocol;
 };
   
 } // Namespace ns3
diff --git a/model/ccnx-l4-protocol.cc b/model/ccnx-l4-protocol.cc
index 8c4d400..9cdd0a1 100644
--- a/model/ccnx-l4-protocol.cc
+++ b/model/ccnx-l4-protocol.cc
@@ -23,6 +23,8 @@
 
 #include "ns3/uinteger.h"
 
+NS_LOG_COMPONENT_DEFINE ("CcnxL4Protocol");
+
 namespace ns3 {
 
 NS_OBJECT_ENSURE_REGISTERED (CcnxL4Protocol);
@@ -36,8 +38,70 @@
   return tid;
 }
 
+CcnxL4Protocol::CcnxL4Protocol ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
 CcnxL4Protocol::~CcnxL4Protocol ()
 {
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void 
+CcnxL4Protocol::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the udp stack and link it to the ipv4 object
+ * present in the node along with the socket factory
+ */
+void
+CcnxL4Protocol::NotifyNewAggregate ()
+{
+  if (m_node == 0)
+    {
+      Ptr<Node> node = this->GetObject<Node> ();
+      if (node != 0)
+        {
+          Ptr<Ccnx> ccnx = this->GetObject<Ccnx> ();
+          if (ccnx != 0)
+            {
+              this->SetNode (node);
+              ccnx->Insert (this);
+              // Ptr<UdpSocketFactoryImpl> udpFactory = CreateObject<UdpSocketFactoryImpl> ();
+              // udpFactory->SetUdp (this);
+              // node->AggregateObject (udpFactory);
+              this->SetDownTarget (MakeCallback (&Ccnx::Send, ccnx));
+            }
+        }
+    }
+  Object::NotifyNewAggregate ();
+}
+
+void
+CcnxL4Protocol::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  m_node = 0;
+  m_downTarget.Nullify ();
+  CcnxL4Protocol::DoDispose ();
+}
+
+void
+SetDownTarget (DownTargetCallback cb)
+{
+  m_downTarget = cb;
+}
+
+DownTargetCallback
+GetDownTarget (void) const
+{
+  retur m_downTarget;
 }
 
 } //namespace ns3
diff --git a/model/ccnx-l4-protocol.h b/model/ccnx-l4-protocol.h
index 14aceef..e0a6aed 100644
--- a/model/ccnx-l4-protocol.h
+++ b/model/ccnx-l4-protocol.h
@@ -48,8 +48,11 @@
 
   static TypeId GetTypeId (void);
 
+  CcnxL4Protocol ();
   virtual ~CcnxL4Protocol ();
 
+  void SetNode (Ptr<Node> node);
+
   /**
    * \param p packet to forward up
    * \param header Ccnx Header information
@@ -60,7 +63,7 @@
    */
   virtual enum RxStatus Receive (Ptr<Packet> p,
                                  CcnxHeader const &header,
-                                 Ptr<CcnxInterface> incomingInterface) = 0;
+                                 Ptr<CcnxInterface> incomingInterface);
 
   typedef Callback<void,Ptr<Packet>, Ptr<CcnxRoute> > DownTargetCallback;
   /**
@@ -69,14 +72,25 @@
    *
    * \param cb current Callback for the L4 protocol
    */
-  virtual void SetDownTarget (DownTargetCallback cb) = 0;
+  virtual void SetDownTarget (DownTargetCallback cb);
   /**
    * This method allows a caller to get the current down target callback
    * set for this L4 protocol, for
    *
    * \return current Callback for the L4 protocol
    */
-  virtual DownTargetCallback GetDownTarget (void) const = 0;
+  virtual DownTargetCallback GetDownTarget (void) const;
+
+protected:
+  virtual void DoDispose (void);
+  /*
+   * This function will notify other components connected to the node that a new stack member is now connected
+   * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+   */
+  virtual void NotifyNewAggregate ();
+
+private:
+  DownTargetCallback m_downTarget;
 };
 
 } // Namespace ns3
diff --git a/model/ccnx-local-face.cc b/model/ccnx-local-face.cc
new file mode 100644
index 0000000..aeb2002
--- /dev/null
+++ b/model/ccnx-local-face.cc
@@ -0,0 +1,104 @@
+/* -*- 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:
+ *
+ */
+
+#include "ccnx-local-face.h"
+
+#include "ns3/ccnx-address.h"
+#include "ns3/ccnx-l3-protocol.h"
+#include "ns3/net-device.h"
+#include "ns3/log.h"
+#include "ns3/packet.h"
+#include "ns3/node.h"
+#include "ns3/pointer.h"
+#include "ns3/assert.h" 
+
+NS_LOG_COMPONENT_DEFINE ("CcnxLocalFace");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxLocalFace);
+
+TypeId 
+CcnxLocalFace::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxLocalFace")
+    .SetParent<Object> ()
+  ;
+  return tid;
+}
+
+/** 
+ * By default, Ccnx interface are created in the "down" state
+ *  with no IP addresses.  Before becoming useable, the user must 
+ * invoke SetUp on them once an Ccnx address and mask have been set.
+ */
+CcnxLocalFace::CcnxLocalFace () 
+{
+  NS_LOG_FUNCTION (this);
+}
+
+CcnxLocalFace::~CcnxLocalFace ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+CcnxLocalFace::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  CcnxFace::DoDispose ();
+}
+
+void 
+CcnxLocalFace::SetDevice (Ptr<NetDevice> device)
+{
+  assert (false);
+}
+
+Ptr<NetDevice>
+CcnxLocalFace::GetDevice (void) const
+{
+  assert (false)
+}
+
+
+
+void
+CcnxLocalFace::Send (Ptr<Packet> p)
+{
+  NS_LOG_FUNCTION (*p);
+  if (!IsUp ())
+    {
+      return;
+    }
+
+  // m_device->Send (p, m_device->GetBroadcast (), 
+  //                 CcnxL3Protocol::PROT_NUMBER);
+}
+
+std::ostream& operator<< (std::ostream& os, CcnxLocalFace const& localFace)
+{
+  os << "dev=local";
+  return os;
+}
+
+}; // namespace ns3
+
diff --git a/model/ccnx-local-face.h b/model/ccnx-local-face.h
new file mode 100644
index 0000000..33d884a
--- /dev/null
+++ b/model/ccnx-local-face.h
@@ -0,0 +1,74 @@
+/* -*- 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
+ *
+ * Authors: 
+ */
+#ifndef CCNX_LOCAL_FACE_H
+#define CCNX_LOCAL_FACE_H
+
+#include "ccnx-face.h"
+
+namespace ns3 {
+
+class NetDevice;
+class Packet;
+class Node;
+
+/**
+ * \brief The Ccnx representation of a network interface
+ *
+ * This class roughly corresponds to the struct in_device
+ * of Linux; the main purpose is to provide address-family
+ * specific information (addresses) about an interface.
+ *
+ * By default, Ccnx interface are created in the "down" state
+ * no IP addresses.  Before becoming useable, the user must 
+ * add an address of some type and invoke Setup on them.
+ */
+class CcnxLocalFace  : public CcnxFace
+{
+public:
+  static TypeId GetTypeId (void);
+
+  CcnxLocalFace ();
+  virtual ~CcnxLocalFace();
+
+  // Create ();
+
+  // Create (Name::Components);
+
+  // typedef callback ?
+  
+  /**
+   * \param p packet to send
+   */ 
+  virtual void Send (Ptr<Packet> p);
+
+protected:
+  virtual void DoDispose (void);
+
+private:
+  /** disabled for LocalFace **/
+  virtual Ptr<NetDevice> GetDevice (void) const;
+  virtual void SetDevice (Ptr<NetDevice> device);
+};
+
+std::ostream& operator<< (std::ostream& os, CcnxLocalFace const& localFace);
+
+} // namespace ns3
+
+#endif
diff --git a/model/ccnx-route.cc b/model/ccnx-route.cc
index 704f08c..98e8b7b 100644
--- a/model/ccnx-route.cc
+++ b/model/ccnx-route.cc
@@ -19,7 +19,7 @@
 
 #include "ccnx-route.h"
 
-#include "ns3/net-device.h"
+#include "ns3/ccnx-face.h"
 #include "ns3/assert.h"
 
 namespace ns3 {
@@ -41,20 +41,20 @@
 }
 
 void
-CcnxRoute::SetOutputDevice (Ptr<NetDevice> outputDevice)
+CcnxRoute::SetOutputFace (Ptr<CcnxFace> outputFace)
 {
-  m_outputDevice = outputDevice;
+  m_outputFace = outputFace;
 }
 
-Ptr<NetDevice>
-CcnxRoute::GetOutputDevice (void) const
+Ptr<CcnxFace>
+CcnxRoute::GetOutputFace (void) const
 {
-  return m_outputDevice;
+  return m_outputFace;
 }
 
 std::ostream& operator<< (std::ostream& os, CcnxRoute const& route)
 {
-  os << "prefix=" << route.GetPrefix () << ", dev=" << route.GetOutputDevice ()->GetIfIndex ();
+  os << "prefix=" << route.GetPrefix () << ", " << route.GetOutputFace ();
   return os;
 }
 
diff --git a/model/ccnx-route.h b/model/ccnx-route.h
index 9502330..c3d7e5e 100644
--- a/model/ccnx-route.h
+++ b/model/ccnx-route.h
@@ -24,10 +24,11 @@
 #include <ostream>
 
 #include "ns3/simple-ref-count.h"
+#include "ns3/name-components.h"
 
 namespace ns3 {
   
-class NetDevice;
+class CcnxFace;
 
 /**
  * \ingroup ccnxRouting
@@ -56,20 +57,19 @@
    *
    * \param outputDevice pointer to NetDevice for outgoing packets
    */
-  void SetOutputDevice (Ptr<NetDevice> outputDevice);
+  void SetOutputFace (Ptr<CcnxFace> outputDevice);
   /**
    * \return pointer to NetDevice for outgoing packets
    */
-  Ptr<NetDevice> GetOutputDevice (void) const;
+  Ptr<CcnxFace> GetOutputFace (void) const;
 
 private:
   Name::Components m_prefix;
-  Ptr<NetDevice> m_outputDevice;
+  Ptr<CcnxFace> m_outputFace;
 };
 
 std::ostream& operator<< (std::ostream& os, CcnxRoute const& route);
 
-} //namespace NDNabstraction
 } //namespace ns3
 
 #endif /* CCNX_ROUTE_H */
diff --git a/model/ccnx.cc b/model/ccnx.cc
index 8a5e6d0..f54d1b0 100644
--- a/model/ccnx.cc
+++ b/model/ccnx.cc
@@ -21,6 +21,7 @@
 #include "ns3/assert.h" 
 #include "ns3/node.h" 
 #include "ns3/boolean.h"
+
 #include "ccnx.h"
 
 namespace ns3 {
diff --git a/model/ccnx.h b/model/ccnx.h
index 9196067..40e2678 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -15,7 +15,7 @@
  * 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>
+ * Author: 
  */
 #ifndef CCNX_H
 #define CCNX_H
@@ -90,12 +90,12 @@
    * to disable it, you can invoke Ccnx::SetDown which will
    * make sure that it is never used during packet forwarding.
    */
-  virtual uint32_t AddInterface (Ptr<NetDevice> device) = 0;
+  virtual uint32_t AddFace (Ptr<CcnxFace> face) = 0;
 
   /**
    * \returns the number of interfaces added by the user.
    */
-  virtual uint32_t GetNInterfaces (void) const = 0;
+  virtual uint32_t GetNFaces (void) const = 0;
 
   /**
    * \param packet packet to send
@@ -104,63 +104,63 @@
    * Higher-level layers call this method to send a packet
    * down the stack to the MAC and PHY layers.
    */
-  virtual void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route) = 0;
+  // virtual void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route) = 0;
 
   /**
-   * \param interface The interface number of an Ccnx interface.
-   * \returns The NetDevice associated with the Ccnx interface number.
+   * \param face The face number of an Ccnx interface.
+   * \returns The CcnxFace associated with the Ccnx face number.
    */
-  virtual Ptr<NetDevice> GetNetDevice (uint32_t interface) = 0;
+  virtual Ptr<CcnxFace> GetFace (uint32_t face) = 0;
+
+  // /**
+  //  * \param face CcnxFace object pointer 
+  //  * \returns The interface number of an Ccnx face or -1 if not found.
+  //  */
+  // virtual int32_t GetFaceForDevice (Ptr<const CcnxFace> face) const = 0;
 
   /**
-   * \param device The NetDevice for an CcnxInterface
-   * \returns The interface number of an Ccnx interface or -1 if not found.
-   */
-  virtual int32_t GetInterfaceForDevice (Ptr<const NetDevice> device) const = 0;
-
-  /**
-   * \param interface The interface number of an Ccnx interface
+   * \param face The face number of an Ccnx face
    * \param metric routing metric (cost) associated to the underlying 
    *          Ccnx interface
    */
-  virtual void SetMetric (uint32_t interface, uint16_t metric) = 0;
+  virtual void SetMetric (uint32_t face, uint16_t metric) = 0;
 
   /**
-   * \param interface The interface number of an Ccnx interface
+   * \param face The interface number of an Ccnx interface
    * \returns routing metric (cost) associated to the underlying 
    *          Ccnx interface
    */
-  virtual uint16_t GetMetric (uint32_t interface) const = 0;
+  virtual uint16_t GetMetric (uint32_t face) const = 0;
 
   /**
-   * \param interface Interface number of Ccnx interface
+   * \param face Interface number of Ccnx interface
    * \returns the Maximum Transmission Unit (in bytes) associated
    *          to the underlying Ccnx interface
    */
-  virtual uint16_t GetMtu (uint32_t interface) const = 0;
+  virtual uint16_t GetMtu (uint32_t face) const = 0;
 
   /**
-   * \param interface Interface number of Ccnx interface
+   * \param face Interface number of Ccnx interface
    * \returns true if the underlying interface is in the "up" state,
    *          false otherwise.
    */
-  virtual bool IsUp (uint32_t interface) const = 0;
+  virtual bool IsUp (uint32_t face) const = 0;
 
   /**
-   * \param interface Interface number of Ccnx interface
+   * \param face Interface number of Ccnx interface
    * 
    * Set the interface into the "up" state. In this state, it is
    * considered valid during Ccnx forwarding.
    */
-  virtual void SetUp (uint32_t interface) = 0;
+  virtual void SetUp (uint32_t face) = 0;
 
   /**
-   * \param interface Interface number of Ccnx interface
+   * \param face Interface number of Ccnx interface
    *
    * Set the interface into the "down" state. In this state, it is
    * ignored during Ccnx forwarding.
    */
-  virtual void SetDown (uint32_t interface) = 0;
+  virtual void SetDown (uint32_t face) = 0;
 };
 
 } // namespace ns3