Updating code to the state that it compiles
diff --git a/model/ccnx-face.cc b/model/ccnx-face.cc
index 6ce6b92..e19dc57 100644
--- a/model/ccnx-face.cc
+++ b/model/ccnx-face.cc
@@ -15,18 +15,14 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Author:
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  *
  */
 
 #include "ccnx-face.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"
 
 NS_LOG_COMPONENT_DEFINE ("CcnxFace");
 
@@ -49,10 +45,10 @@
  * invoke SetUp on them once an Ccnx address and mask have been set.
  */
 CcnxFace::CcnxFace () 
-  : m_ifup (false)
-  , m_metric (1)
+  : m_metric (1)
   , m_node (0)
-  , m_device (0)
+  , m_ifup (false)
+  , m_id ((uint32_t)-1)
 {
   NS_LOG_FUNCTION (this);
 }
@@ -62,12 +58,21 @@
   NS_LOG_FUNCTION_NOARGS ();
 }
 
+CcnxFace::CcnxFace (const CcnxFace &)
+{
+}
+
+CcnxFace& CcnxFace::operator= (const CcnxFace &)
+{
+  return *this;
+}
+
+  
 void
 CcnxFace::DoDispose (void)
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_node = 0;
-  m_device = 0;
   Object::DoDispose ();
 }
 
@@ -77,18 +82,6 @@
   m_node = node;
 }
 
-void 
-CcnxFace::SetDevice (Ptr<NetDevice> device)
-{
-  m_device = device;
-}
-
-Ptr<NetDevice>
-CcnxFace::GetDevice (void) const
-{
-  return m_device;
-}
-
 void
 CcnxFace::SetMetric (uint16_t metric)
 {
@@ -136,27 +129,16 @@
   m_ifup = false;
 }
 
-void
-CcnxFace::Send (Ptr<Packet> packet)
+bool
+CcnxFace::operator== (const CcnxFace &face) const
 {
-  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;
-    }
-
-  m_device->Send (packet, m_device->GetBroadcast (), 
-                  CcnxL3Protocol::ETHERNET_FRAME_TYPE);
+  return (m_node->GetId () == face.m_node->GetId ()) &&
+    (m_id == face.m_id);
 }
 
-std::ostream& operator<< (std::ostream& os, CcnxFace const& face)
+std::ostream& operator<< (std::ostream& os, const CcnxFace &face)
 {
-  os << "dev=" << face.GetDevice ()->GetIfIndex ();
+  os << "id=" << face.GetId ();
   return os;
 }
 
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index 121c146..787bfa0 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -15,12 +15,12 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * Authors: 
+ * Authors: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
+
 #ifndef CCNX_FACE_H
 #define CCNX_FACE_H
 
-#include <list>
 #include <ostream>
 
 #include "ns3/ptr.h"
@@ -28,12 +28,15 @@
 
 namespace ns3 {
 
-class NetDevice;
 class Packet;
 class Node;
 
 /**
  * \ingroup ccnx
+ * \defgroup ccnx-face
+ */
+/**
+ * \ingroup ccnx-face
  * \brief Virtual class defining CCNx face
  *
  * This class defines basic functionality of CCNx face. Face is core
@@ -51,7 +54,7 @@
    * \param face Face from which packet has been received
    * \param packet Received packet
    */
-  typedef Callback<void,Ptr<CcnxFace>,Ptr<Packet> > ProtocolHandler;
+  typedef Callback<void,const Ptr<CcnxFace>&,const Ptr<Packet>& > ProtocolHandler;
   
   /**
    * \brief Interface ID
@@ -73,7 +76,7 @@
    *
    * This method should call protocol-dependent registration function
    */
-  void RegisterProtocolHandler (ProtocolHandler handler) = 0;
+  virtual void RegisterProtocolHandler (ProtocolHandler handler) = 0;
   
   /**
    * \brief Send packet on a face
@@ -131,21 +134,59 @@
    */
   virtual bool IsDown () const;
 
+  /**
+   * \brief Set node Id
+   *
+   * Id is purely informative and should not be used for any other purpose
+   *
+   * \param id id to set
+   */
+  inline void
+  SetId (uint32_t id);
+
+  /**
+   * \brief Get node Id
+   *
+   * Id is purely informative and should not be used for any other purpose
+   *
+   * \returns id id to set
+   */
+  inline uint32_t
+  GetId () const;
+
+  bool
+  operator== (const CcnxFace &face) const;
+  
 protected:
   virtual void DoDispose (void);
 
 private:
-  CcnxFace (const CcnxFace &) {} ///< Disabled copy constructor
-  CcnxFace& operator= (const CcnxFace &) {} ///< Disabled copy operator
+  CcnxFace (const CcnxFace &); ///< \brief Disabled copy constructor
+  CcnxFace& operator= (const CcnxFace &); ///< \brief Disabled copy operator
   
 protected:
-  bool m_ifup;
-  uint32_t m_id; ///< id of the interface in the CCNx stack (per-node uniqueness)
-  uint16_t m_metric;
-  Ptr<Node> m_node;
+  uint16_t m_metric; ///< \brief Routing/forwarding metric
+  Ptr<Node> m_node; ///< \brief Smart pointer to Node
+  ProtocolHandler m_protocolHandler; ///< Callback via which packets are getting send to CCNx stack
+
+private:
+  bool m_ifup; ///< \brief flag indicating that the interface is UP 
+  uint32_t m_id; ///< \brief id of the interface in CCNx stack (per-node uniqueness)
 };
 
-std::ostream& operator<< (std::ostream& os, CcnxFace const& face);
+std::ostream& operator<< (std::ostream& os, const CcnxFace &face);
+
+void
+CcnxFace::SetId (uint32_t id)
+{
+  m_id = id;
+}
+
+uint32_t
+CcnxFace::GetId () const
+{
+  return m_id;
+}
 
 } // namespace ns3
 
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index d698356..07bf848 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -38,6 +38,7 @@
 #include "ccnx-interest-header.h"
 #include "ccnx-content-object-header.h"
 
+#include <boost/foreach.hpp>
 
 NS_LOG_COMPONENT_DEFINE ("CcnxL3Protocol");
 
@@ -140,12 +141,12 @@
 uint32_t 
 CcnxL3Protocol::AddFace (const Ptr<CcnxFace> &face)
 {
-  NS_LOG_FUNCTION (this << *face);
+  NS_LOG_FUNCTION (this << &face);
 
   face->SetNode (m_node);
   face->SetId (m_faceCounter); // sets a unique ID of the face. This ID serves only informational purposes
 
-  face->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::ReceiveFromLower, this));
+  face->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::Receive, this));
   // if (face->GetDevice() != 0)
   //   {
   //     m_node->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::ReceiveFromLower, this), 
@@ -157,13 +158,13 @@
   return m_faceCounter;
 }
 
-
 Ptr<CcnxFace>
 CcnxL3Protocol::GetFace (uint32_t index) const
 {
-  if (index < m_faces.size ())
+  BOOST_FOREACH (const Ptr<CcnxFace> &face, m_faces) // this function is not supposed to be called often, so linear search is fine
     {
-      return m_faces[index];
+      if (face->GetId () == index)
+        return face;
     }
   return 0;
 }
@@ -174,39 +175,17 @@
   return m_faces.size ();
 }
 
-Ptr<CcnxFace>
-CcnxL3Protocol::GetFaceForDevice (Ptr<const NetDevice> device) const
-{
-  for (CcnxFaceList::const_iterator i = m_faces.begin (); 
-       i != m_faces.end (); 
-       i++)
-    {
-      if ((*i)->GetDevice () == device)
-        {
-          return *i;
-        }
-    }
-
-  NS_ASSERT_MSG (false, "Should never get to this place" );
-  return 0;
-}
-
 // Callback from lower layer
 void 
-CcnxL3Protocol::ReceiveFromLower ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
-                          const Address &to, NetDevice::PacketType packetType)
+CcnxL3Protocol::Receive (const Ptr<CcnxFace> &face, const Ptr<Packet> &p)
 {
-  NS_LOG_FUNCTION (this << &device << p << protocol <<  from);
-
-  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<  m_node->GetId ());
-
-  Ptr<CcnxFace> ccnxFace = GetFaceForDevice (device);
+  NS_LOG_LOGIC ("Packet from face " << &face << " received on node " <<  m_node->GetId ());
 
   Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
   try
     {
       Ptr<Header> header = CcnxHeaderHelper::CreateCorrectCcnxHeader (p);
-      ReceiveAndProcess (ccnxFace, header, packet);  // header should serve as overloaded method selector... not sure whether it works with this "smart" pointers...
+      ReceiveAndProcess (face, header, packet);  // header should serve as overloaded method selector... not sure whether it works with this "smart" pointers...
     }
   catch (CcnxUnknownHeaderException)
     {
@@ -215,7 +194,9 @@
 }
 
 // Processing Interests
-void CcnxL3Protocol::ReceiveAndProcess (Ptr<CcnxFace> incomingFace, Ptr<CcnxInterestHeader> header, Ptr<Packet> packet)
+void CcnxL3Protocol::ReceiveAndProcess (const Ptr<CcnxFace> &incomingFace,
+                                        const Ptr<CcnxInterestHeader> &header,
+                                        const Ptr<Packet> &packet)
 {
   if (incomingFace->IsUp ())
     {
@@ -239,7 +220,9 @@
 }
 
 // Processing ContentObjects
-void CcnxL3Protocol::ReceiveAndProcess (Ptr<CcnxFace> incomingFace, Ptr<CcnxContentObjectHeader> header, Ptr<Packet> packet)
+void CcnxL3Protocol::ReceiveAndProcess (const Ptr<CcnxFace> &incomingFace,
+                                        const Ptr<CcnxContentObjectHeader> &header,
+                                        const Ptr<Packet> &packet)
 {
   if (incomingFace->IsUp ())
     {
@@ -260,7 +243,7 @@
 
 
 void
-CcnxL3Protocol::Send (Ptr<Packet> packet, const Ptr<CcnxFace> &face)
+CcnxL3Protocol::Send (const Ptr<CcnxFace> &face, const Ptr<Packet> &packet)
 {
   // NS_LOG_FUNCTION (this << "packet: " << packet << ", route: "<< route);
   
@@ -286,59 +269,4 @@
 }
 
 
-void 
-CcnxL3Protocol::SetMetric (uint32_t i, uint16_t metric)
-{
-  NS_LOG_FUNCTION (this << i << metric);
-  Ptr<CcnxFace> face = GetFace (i);
-  face->SetMetric (metric);
-}
-
-uint16_t
-CcnxL3Protocol::GetMetric (uint32_t i) const
-{
-  Ptr<const CcnxFace> face = GetFace (i);
-  return face->GetMetric ();
-}
-
-uint16_t 
-CcnxL3Protocol::GetMtu (uint32_t i) const
-{
-  Ptr<CcnxFace> face = GetFace (i);
-  return face->GetDevice ()->GetMtu ();
-}
-
-bool 
-CcnxL3Protocol::IsUp (uint32_t i) const
-{
-  Ptr<CcnxFace> interface = GetFace (i);
-  return interface->IsUp ();
-}
-
-void 
-CcnxL3Protocol::SetUp (uint32_t i)
-{
-  NS_LOG_FUNCTION (this << i);
-  Ptr<CcnxFace> interface = GetFace (i);
-  interface->SetUp ();
-
-  if (m_forwardingStrategy != 0)
-    {
-      m_forwardingStrategy->NotifyInterfaceUp (i);
-    }
-}
-
-void 
-CcnxL3Protocol::SetDown (uint32_t ifaceIndex)
-{
-  NS_LOG_FUNCTION (this << ifaceIndex);
-  Ptr<CcnxFace> interface = GetFace (ifaceIndex);
-  interface->SetDown ();
-
-  if (m_forwardingStrategy != 0)
-    {
-      m_forwardingStrategy->NotifyInterfaceDown (ifaceIndex);
-    }
-}
-
 } //namespace ns3
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 28a8d06..4743bdd 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -66,7 +66,7 @@
    *
    * \return interface ID
    */
-  static TypeId GetTypeId (void);
+  static TypeId GetTypeId ();
 
   static const uint16_t ETHERNET_FRAME_TYPE; ///< \brief Ethernet Frame Type of CCNx
   static const uint16_t IP_PROTOCOL_TYPE;    ///< \brief IP protocol type of CCNx
@@ -102,22 +102,15 @@
   // functions defined in base class Ccnx
   
   void SetForwardingStrategy (Ptr<CcnxForwardingStrategy> forwardingStrategy);
-  Ptr<CcnxForwardingStrategy> GetForwardingStrategy (void) const;
+  Ptr<CcnxForwardingStrategy> GetForwardingStrategy () const;
 
-  virtual void Send (const Ptr<CcnxFace> &face, Ptr<Packet> packet);
-  virtual void ReceiveFromLower (const Ptr<Face> &device, Ptr<const Packet> p);
+  virtual void Send (const Ptr<CcnxFace> &face, const Ptr<Packet> &packet);
+  virtual void Receive (const Ptr<CcnxFace> &device, const Ptr<Packet> &p);
 
   virtual uint32_t AddFace (const Ptr<CcnxFace> &face);
-  virtual uint32_t GetNFaces (void) const;
+  virtual uint32_t GetNFaces () const;
   virtual Ptr<CcnxFace> GetFace (uint32_t face) const;
 
-  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:
   /**
    * Actual processing of incoming CCNx packets. Also processing packets coming from local apps
@@ -125,7 +118,9 @@
    * Processing Interest packets
    */
   virtual void
-  ReceiveAndProcess (Ptr<CcnxFace> face, Ptr<CcnxInterestHeader> header, Ptr<Packet> p);
+  ReceiveAndProcess (const Ptr<CcnxFace> &face,
+                     const Ptr<CcnxInterestHeader> &header,
+                     const Ptr<Packet> &p);
 
   
   /**
@@ -134,7 +129,9 @@
    * Processing ContentObject packets
    */
   virtual void
-  ReceiveAndProcess (Ptr<CcnxFace> face, Ptr<CcnxContentObjectHeader> header, Ptr<Packet> p);
+  ReceiveAndProcess (const Ptr<CcnxFace> &face,
+                     const Ptr<CcnxContentObjectHeader> &header,
+                     const Ptr<Packet> &p);
 
 protected:
   virtual void DoDispose (void);
@@ -150,11 +147,6 @@
   CcnxL3Protocol &operator = (const CcnxL3Protocol &); ///< copy operator is disabled
 
   /**
-   * Helper function to get CcnxFace from NetDevice
-   */
-  Ptr<CcnxFace> GetFaceForDevice (Ptr<const NetDevice> device) const;
-
-  /**
    * \brief Fake function. should never be called. Just to trick C++ to compile
    */
   virtual void
diff --git a/model/ccnx-local-face.cc b/model/ccnx-local-face.cc
index 4a6fa55..ea2a84b 100644
--- a/model/ccnx-local-face.cc
+++ b/model/ccnx-local-face.cc
@@ -21,8 +21,6 @@
 
 #include "ccnx-local-face.h"
 
-#include "ns3/ccnx-l3-protocol.h"
-#include "ns3/net-device.h"
 #include "ns3/log.h"
 #include "ns3/packet.h"
 #include "ns3/node.h"
@@ -39,16 +37,11 @@
 CcnxLocalFace::GetTypeId (void)
 {
   static TypeId tid = TypeId ("ns3::CcnxLocalFace")
-    .SetParent<Object> ()
+    .SetParent<CcnxFace> ()
   ;
   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);
@@ -66,16 +59,10 @@
   CcnxFace::DoDispose ();
 }
 
-void 
-CcnxLocalFace::SetDevice (Ptr<NetDevice> device)
+void
+CcnxLocalFace::RegisterProtocolHandler (ProtocolHandler handler)
 {
-  NS_ASSERT_MSG (false, "It is impossible to set device to LocalFace");
-}
-
-Ptr<NetDevice>
-CcnxLocalFace::GetDevice (void) const
-{
-  return 0;
+  m_protocolHandler = handler;
 }
 
 void
@@ -91,7 +78,7 @@
   //                 CcnxL3Protocol::PROT_NUMBER);
 }
 
-std::ostream& operator<< (std::ostream& os, CcnxLocalFace const& localFace)
+std::ostream& operator<< (std::ostream& os, const CcnxLocalFace &localFace)
 {
   os << "dev=local";
   return os;
diff --git a/model/ccnx-local-face.h b/model/ccnx-local-face.h
index 118333a..792ef4d 100644
--- a/model/ccnx-local-face.h
+++ b/model/ccnx-local-face.h
@@ -24,50 +24,52 @@
 
 namespace ns3 {
 
-class NetDevice;
-class Packet;
-class Node;
-
 /**
- * \brief The Ccnx representation of a network interface
+ * \ingroup ccnx-face
+ * \brief Implementation of application CCNx 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.
+ * This class defines basic functionality of CCNx face. Face is core
+ * component responsible for actual delivery of data packet to and
+ * from CCNx stack
  *
- * 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.
+ * \see CcnxLocalFace, CcnxNetDeviceFace, CcnxIpv4Face, CcnxUdpFace
  */
 class CcnxLocalFace  : public CcnxFace
 {
 public:
+  /**
+   * \brief Interface ID
+   *
+   * \return interface ID
+   */
   static TypeId GetTypeId (void);
 
+  /**
+   * \brief Default constructor
+   */
   CcnxLocalFace ();
   virtual ~CcnxLocalFace();
-
-  // Create ();
-
-  // Create (Name::Components);
-
-  // typedef callback ?
   
-  /**
-   * \param p packet to send
-   */ 
+  ////////////////////////////////////////////////////////////////////
+  // methods overloaded from CcnxFace
+  
+  virtual void RegisterProtocolHandler (ProtocolHandler handler);
+
   virtual void Send (Ptr<Packet> p);
 
+  ////////////////////////////////////////////////////////////////////
+
+  /// \todo Need methods to implement application hooks
+  
 protected:
   virtual void DoDispose (void);
 
 private:
-  /** disabled for LocalFace **/
-  virtual Ptr<NetDevice> GetDevice (void) const;
-  virtual void SetDevice (Ptr<NetDevice> device);
+  CcnxLocalFace (const CcnxLocalFace &); ///< \brief Disabled copy constructor
+  CcnxLocalFace& operator= (const CcnxLocalFace &); ///< \brief Disabled copy operator
 };
 
-std::ostream& operator<< (std::ostream& os, CcnxLocalFace const& localFace);
+std::ostream& operator<< (std::ostream& os, const CcnxLocalFace &localFace);
 
 } // namespace ns3
 
diff --git a/model/ccnx-net-device-face.cc b/model/ccnx-net-device-face.cc
new file mode 100644
index 0000000..37a3555
--- /dev/null
+++ b/model/ccnx-net-device-face.cc
@@ -0,0 +1,142 @@
+/* -*- 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ *
+ */
+
+#include "ccnx-net-device-face.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"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxNetDeviceFace");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxNetDeviceFace);
+
+TypeId 
+CcnxNetDeviceFace::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::CcnxNetDeviceFace")
+    .SetParent<CcnxFace> ()
+  ;
+  return tid;
+}
+
+/** 
+ * 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.
+ */
+CcnxNetDeviceFace::CcnxNetDeviceFace () 
+  : m_netDevice (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+CcnxNetDeviceFace::~CcnxNetDeviceFace ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+CcnxNetDeviceFace::CcnxNetDeviceFace (const CcnxNetDeviceFace &)
+{
+}
+
+CcnxNetDeviceFace& CcnxNetDeviceFace::operator= (const CcnxNetDeviceFace &)
+{
+  return *this;
+}
+
+  
+void
+CcnxNetDeviceFace::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_netDevice = 0;
+  Object::DoDispose ();
+}
+
+void 
+CcnxNetDeviceFace::SetNetDevice (Ptr<NetDevice> netDevice)
+{
+  m_netDevice = netDevice;
+}
+
+Ptr<NetDevice>
+CcnxNetDeviceFace::GetNetDevice () const
+{
+  return m_netDevice;
+}
+
+void
+CcnxNetDeviceFace::RegisterProtocolHandler (ProtocolHandler handler)
+{
+  NS_ASSERT_MSG (m_netDevice != 0, "CcnxNetDeviceFace needs to be assigned NetDevice first");
+  
+  m_protocolHandler = handler;
+
+  m_node->RegisterProtocolHandler (MakeCallback (&CcnxNetDeviceFace::ReceiveFromNetDevice, this),
+                                   CcnxL3Protocol::ETHERNET_FRAME_TYPE, m_netDevice, true/*promiscuous mode*/);
+}
+
+void
+CcnxNetDeviceFace::Send (Ptr<Packet> packet)
+{
+  NS_ASSERT_MSG (packet->GetSize () <= m_netDevice->GetMtu (), 
+                 "Packet size " << packet->GetSize () << " exceeds device MTU "
+                                << m_netDevice->GetMtu ()
+                                << " for Ccnx; fragmentation not supported");
+
+  NS_LOG_FUNCTION (*packet);
+  if (!IsUp ())
+    {
+      return;
+    }
+
+  m_netDevice->Send (packet, m_netDevice->GetBroadcast (), 
+                  CcnxL3Protocol::ETHERNET_FRAME_TYPE);
+}
+
+// callback
+void
+CcnxNetDeviceFace::ReceiveFromNetDevice (Ptr<NetDevice> device,
+                                         Ptr<const Packet> p,
+                                         uint16_t protocol,
+                                         const Address &from,
+                                         const Address &to,
+                                         NetDevice::PacketType packetType)
+{
+  // bla bla bla
+}
+
+
+std::ostream& operator<< (std::ostream& os, const CcnxNetDeviceFace &face)
+{
+  return operator<< (os, static_cast<const CcnxFace&> (face)); // just call parent class for now
+  // os << "id=" << face.GetId ();
+  // return os;
+}
+
+}; // namespace ns3
+
diff --git a/model/ccnx-net-device-face.h b/model/ccnx-net-device-face.h
new file mode 100644
index 0000000..397d6c1
--- /dev/null
+++ b/model/ccnx-net-device-face.h
@@ -0,0 +1,103 @@
+/* -*- 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: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef CCNX_NET_DEVICE_FACE_H
+#define CCNX_NET_DEVICE_FACE_H
+
+#include "ccnx-face.h"
+#include "ns3/net-device.h"
+
+namespace ns3 {
+
+class Address;
+  
+/**
+ * \ingroup ccnx-face
+ * \brief Implementation of layer-2 (Ethernet) CCNx face
+ *
+ * This class defines basic functionality of CCNx face. Face is core
+ * component responsible for actual delivery of data packet to and
+ * from CCNx stack
+ *
+ * \see CcnxLocalFace, CcnxNetDeviceFace, CcnxIpv4Face, CcnxUdpFace
+ */
+class CcnxNetDeviceFace  : public CcnxFace
+{
+public:
+  /**
+   * \brief Interface ID
+   *
+   * \return interface ID
+   */
+  static TypeId GetTypeId (void);
+
+  /**
+   * \brief Default constructor
+   */
+  CcnxNetDeviceFace ();
+  virtual ~CcnxNetDeviceFace();
+
+  ////////////////////////////////////////////////////////////////////
+  // methods overloaded from CcnxFace
+  
+  virtual void RegisterProtocolHandler (ProtocolHandler handler);
+
+  virtual void Send (Ptr<Packet> p);
+
+  ////////////////////////////////////////////////////////////////////
+
+  /**
+   * \brief Associate NetDevice object with face
+   *
+   * \param node smart pointer to a NetDevice object
+   */
+  void SetNetDevice (Ptr<NetDevice> node);
+
+  /**
+   * \brief Get NetDevice associated with the face
+   *
+   * \returns smart pointer to NetDevice associated with the face
+   */
+  Ptr<NetDevice> GetNetDevice () const;
+  
+protected:
+  virtual void DoDispose ();
+
+private:
+  CcnxNetDeviceFace (const CcnxNetDeviceFace &); ///< \brief Disabled copy constructor
+  CcnxNetDeviceFace& operator= (const CcnxNetDeviceFace &); ///< \brief Disabled copy operator
+
+  // callback
+  void ReceiveFromNetDevice (Ptr<NetDevice> device,
+                             Ptr<const Packet> p,
+                             uint16_t protocol,
+                             const Address &from,
+                             const Address &to,
+                             NetDevice::PacketType packetType);
+
+private:
+  Ptr<NetDevice> m_netDevice; ///< \brief Smart pointer to NetDevice
+};
+
+std::ostream& operator<< (std::ostream& os, const CcnxNetDeviceFace &face);
+
+} // namespace ns3
+
+#endif //CCNX_NET_DEVICE_FACE_H
diff --git a/model/ccnx.h b/model/ccnx.h
index 3ec6058..1cbe428 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -69,44 +69,6 @@
   static TypeId GetTypeId ();
 
   /**
-   * \brief Register a new forwarding strategy to be used by this Ccnx
-   * stack
-   *
-   * This call will replace any forwarding strategy that has been
-   * previously registered.
-   * 
-   * \param forwardingStrategy smart pointer to CcnxForwardingStrategy
-   * object
-   */
-  virtual void SetForwardingStrategy (Ptr<CcnxForwardingStrategy> forwardingStrategy) = 0;
-
-  /**
-   * \brief Get the forwarding strategy being used by this Ccnx stack
-   * 
-   * \returns smart pointer to CcnxForwardingStrategy object, or null
-   * pointer if none
-   */
-  virtual Ptr<CcnxForwardingStrategy> GetForwardingStrategy (void) const = 0;
-
-  /**
-   * \brief Add face to CCNx stack
-   *
-   * \param face smart pointer to CcnxFace-derived object
-   * (CcnxLocalFace, CcnxNetDeviceFace, CcnxUdpFace) \returns the
-   * index of the Ccnx interface added.
-   * 
-   * \see CcnxLocalFace, CcnxNetDeviceFace, CcnxUdpFace
-   */
-  virtual uint32_t AddFace (const Ptr<CcnxFace> &face) = 0;
-
-  /**
-   * \brief Get current number of faces added to CCNx stack
-   *
-   * \returns the number of faces
-   */
-  virtual uint32_t GetNFaces (void) const = 0;
-
-  /**
    * \brief Send a packet to a specified face
    *
    * \param face face where to send this packet
@@ -115,7 +77,8 @@
    * Higher-level layers (forwarding strategy in particular) call this
    * method to send a packet down the stack to the MAC and PHY layers.
    */
-  virtual void Send (const Ptr<CcnxFace> &face, Ptr<Packet> packet) = 0;
+  virtual void
+  Send (const Ptr<CcnxFace> &face, const Ptr<Packet> &packet) = 0;
 
   /**
    * \brief Lower layers calls this method after demultiplexing
@@ -126,13 +89,57 @@
    * \param face face from which packet came from
    * \param p the packet
    */
-  void ReceiveFromLower (const Ptr<Face> &device, Ptr<const Packet> p);
+  virtual void
+  Receive (const Ptr<CcnxFace> &device, const Ptr<Packet> &p) = 0;
+
+  /**
+   * \brief Register a new forwarding strategy to be used by this Ccnx
+   * stack
+   *
+   * This call will replace any forwarding strategy that has been
+   * previously registered.
+   * 
+   * \param forwardingStrategy smart pointer to CcnxForwardingStrategy
+   * object
+   */
+  virtual void
+  SetForwardingStrategy (Ptr<CcnxForwardingStrategy> forwardingStrategy) = 0;
+
+  /**
+   * \brief Get the forwarding strategy being used by this Ccnx stack
+   * 
+   * \returns smart pointer to CcnxForwardingStrategy object, or null
+   * pointer if none
+   */
+  virtual Ptr<CcnxForwardingStrategy>
+  GetForwardingStrategy (void) const = 0;
+
+  /**
+   * \brief Add face to CCNx stack
+   *
+   * \param face smart pointer to CcnxFace-derived object
+   * (CcnxLocalFace, CcnxNetDeviceFace, CcnxUdpFace) \returns the
+   * index of the Ccnx interface added.
+   * 
+   * \see CcnxLocalFace, CcnxNetDeviceFace, CcnxUdpFace
+   */
+  virtual uint32_t
+  AddFace (const Ptr<CcnxFace> &face) = 0;
+
+  /**
+   * \brief Get current number of faces added to CCNx stack
+   *
+   * \returns the number of faces
+   */
+  virtual uint32_t
+  GetNFaces (void) const = 0;
 
   /**
    * \param face The face number of an Ccnx interface.
    * \returns The CcnxFace associated with the Ccnx face number.
    */
-  virtual Ptr<CcnxFace> GetFace (uint32_t face) const = 0;
+  virtual Ptr<CcnxFace>
+  GetFace (uint32_t face) const = 0;
 
 public:
    /**