Merge remote-tracking branch 'ns3irl/ccnx-stack'

diff --git a/apps/stupid-interest-generator.cc b/apps/stupid-interest-generator.cc
index 0dfcf51..8606117 100644
--- a/apps/stupid-interest-generator.cc
+++ b/apps/stupid-interest-generator.cc
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 //
 //  ndn_stupidinterestgenerator.cpp
 //  Abstraction
@@ -11,23 +12,20 @@
 #include "ns3/socket-factory.h"
 #include "ns3/simulator.h"
 
-#include "ns3/interest-header.h"
-#include "ns3/content-object-header.h"
+#include "ns3/ccnx-interest-header.h"
+#include "ns3/ccnx-content-object-header.h"
 
 NS_LOG_COMPONENT_DEFINE ("StupidInterestGenerator");
 
 namespace ns3
 {
-//namespace NDNabstraction
-//{
-    using namespace NDNabstraction;
     
-    NS_OBJECT_ENSURE_REGISTERED (StupidInterestGenerator);
+NS_OBJECT_ENSURE_REGISTERED (StupidInterestGenerator);
     
-    TypeId
-    StupidInterestGenerator::GetTypeId (void)
-    {
-        static TypeId tid = TypeId ("ns3::StupidInterestGenerator")
+TypeId
+StupidInterestGenerator::GetTypeId (void)
+{
+	static TypeId tid = TypeId ("ns3::StupidInterestGenerator")
         .SetParent<Application> ()
         .AddConstructor<StupidInterestGenerator> ()
         .AddAttribute ("Remote", "The address of the destination",
@@ -43,138 +41,137 @@
                        MakeTypeIdAccessor (&StupidInterestGenerator::m_tid),
                        MakeTypeIdChecker ())
         ;
-        return tid;
-    }
+	return tid;
+}
 
-    StupidInterestGenerator::StupidInterestGenerator ()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
-        m_socket = 0;
-        //m_connected = false;
-        //m_residualBits = 0;
-        //m_lastStartTime = Seconds (0);
-        //m_totBytes = 0;
-    }
+StupidInterestGenerator::StupidInterestGenerator ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	m_socket = 0;
+	//m_connected = false;
+	//m_residualBits = 0;
+	//m_lastStartTime = Seconds (0);
+	//m_totBytes = 0;
+}
     
-    StupidInterestGenerator::~StupidInterestGenerator()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
-    }
+StupidInterestGenerator::~StupidInterestGenerator()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+}
     
-    void
-    StupidInterestGenerator::DoDispose (void)
-    {
-        NS_LOG_FUNCTION_NOARGS ();
+void
+StupidInterestGenerator::DoDispose (void)
+{
+	NS_LOG_FUNCTION_NOARGS ();
         
-        m_socket = 0;
-        // chain up
-        Application::DoDispose ();
-    }
+	m_socket = 0;
+	// chain up
+	Application::DoDispose ();
+}
     
-    // Application Methods
-    void StupidInterestGenerator::StartApplication () // Called at time specified by Start
-    {
-        NS_LOG_FUNCTION_NOARGS ();
+// Application Methods
+void StupidInterestGenerator::StartApplication () // Called at time specified by Start
+{
+	NS_LOG_FUNCTION_NOARGS ();
         
-        // Create the socket if not already
-        if (!m_socket)
-        {
-            m_socket = Socket::CreateSocket (GetNode (), m_tid);
-            m_socket->Bind ();
-            m_socket->Connect (m_peer);
-            m_socket->SetAllowBroadcast (true);
-            m_socket->ShutdownRecv ();
-        }
-        // Insure no pending event
-        CancelEvents ();
-        // If we are not yet connected, there is nothing to do here
-        // The ConnectionComplete upcall will start timers at that time
-        //if (!m_connected) return;
-        ScheduleStartEvent ();
-    }
+	// Create the socket if not already
+	if (!m_socket)
+	{
+		m_socket = Socket::CreateSocket (GetNode (), m_tid);
+		m_socket->Bind ();
+		m_socket->Connect (m_peer);
+		m_socket->SetAllowBroadcast (true);
+		m_socket->ShutdownRecv ();
+	}
+	// Insure no pending event
+	CancelEvents ();
+	// If we are not yet connected, there is nothing to do here
+	// The ConnectionComplete upcall will start timers at that time
+	//if (!m_connected) return;
+	ScheduleStartEvent ();
+}
     
-    void StupidInterestGenerator::StopApplication () // Called at time specified by Stop
-    {
-        NS_LOG_FUNCTION_NOARGS ();
+void StupidInterestGenerator::StopApplication () // Called at time specified by Stop
+{
+	NS_LOG_FUNCTION_NOARGS ();
         
-        CancelEvents ();
-        if(m_socket != 0)
-        {
-            m_socket->Close ();
-        }
-        else
-        {
-            NS_LOG_WARN ("OnOffApplication found null socket to close in StopApplication");
-        }
-    }
+	CancelEvents ();
+	if(m_socket != 0)
+	{
+		m_socket->Close ();
+	}
+	else
+	{
+		NS_LOG_WARN ("OnOffApplication found null socket to close in StopApplication");
+	}
+}
     
-    void StupidInterestGenerator::CancelEvents ()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
+void StupidInterestGenerator::CancelEvents ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
         
-        Simulator::Cancel (m_sendEvent);
-        Simulator::Cancel (m_startStopEvent);
-    }
+	Simulator::Cancel (m_sendEvent);
+	Simulator::Cancel (m_startStopEvent);
+}
 
-    void StupidInterestGenerator::ScheduleStartEvent ()
-    {  // Schedules the event to start sending data (switch to the "On" state)
-        NS_LOG_FUNCTION_NOARGS ();
+void StupidInterestGenerator::ScheduleStartEvent ()
+{  // Schedules the event to start sending data (switch to the "On" state)
+	NS_LOG_FUNCTION_NOARGS ();
         
-        Time offInterval = Seconds (m_offTime);
-        NS_LOG_LOGIC ("start at " << offInterval);
-        m_startStopEvent = Simulator::Schedule (offInterval, &StupidInterestGenerator::StartSending, this);
-    }
+	Time offInterval = Seconds (m_offTime);
+	NS_LOG_LOGIC ("start at " << offInterval);
+	m_startStopEvent = Simulator::Schedule (offInterval, &StupidInterestGenerator::StartSending, this);
+}
     
-    // Event handlers
-    void StupidInterestGenerator::StartSending ()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
-        //m_lastStartTime = Simulator::Now ();
-        ScheduleNextTx ();  // Schedule the send packet event
-        //ScheduleStopEvent ();
-    }
+// Event handlers
+void StupidInterestGenerator::StartSending ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	//m_lastStartTime = Simulator::Now ();
+	ScheduleNextTx ();  // Schedule the send packet event
+	//ScheduleStopEvent ();
+}
     
-    void StupidInterestGenerator::StopSending ()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
-        CancelEvents ();
+void StupidInterestGenerator::StopSending ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
+	CancelEvents ();
         
-        ScheduleStartEvent ();
-    }
+	ScheduleStartEvent ();
+}
     
-    // Private helpers
-    void StupidInterestGenerator::ScheduleNextTx ()
-    {
-        NS_LOG_FUNCTION_NOARGS ();
+// Private helpers
+void StupidInterestGenerator::ScheduleNextTx ()
+{
+	NS_LOG_FUNCTION_NOARGS ();
         
 
-        Time nextTime = Seconds(0.); //send now
-        m_sendEvent = Simulator::Schedule (nextTime,
-                                               &StupidInterestGenerator::SendPacket, this);
-    }
+	Time nextTime = Seconds(0.); //send now
+	m_sendEvent = Simulator::Schedule (nextTime,
+									   &StupidInterestGenerator::SendPacket, this);
+}
 
         
-    void StupidInterestGenerator::SendPacket ()
-    {
-        // NS_LOG_FUNCTION_NOARGS ();
-        // NS_LOG_LOGIC ("sending packet at " << Simulator::Now ());
-        // NS_ASSERT (m_sendEvent.IsExpired ());
+void StupidInterestGenerator::SendPacket ()
+{
+	// NS_LOG_FUNCTION_NOARGS ();
+	// NS_LOG_LOGIC ("sending packet at " << Simulator::Now ());
+	// NS_ASSERT (m_sendEvent.IsExpired ());
         
-        // NameBuilder name;
-		// name("prefix1")("prefix2")("filename");
-		InterestHeader ();
+	// NameBuilder name;
+	// name("prefix1")("prefix2")("filename");
+	CcnxInterestHeader ();
 
-		ContentObjectHeader ();
+	CcnxContentObjectHeader ();
 		
-        // const ccn_charbuf *output = name.GetName();
-        // Ptr<InterestPacket> packet = Create<InterestPacket>(name,(uint32_t)output->length);
-        // packet->AddTimeout(4000);
-        // UniformVariable var;
-        // packet->AddNonce(var.GetInteger(1,10000));
-        // m_socket->Send(packet);
+	// const ccn_charbuf *output = name.GetName();
+	// Ptr<InterestPacket> packet = Create<InterestPacket>(name,(uint32_t)output->length);
+	// packet->AddTimeout(4000);
+	// UniformVariable var;
+	// packet->AddNonce(var.GetInteger(1,10000));
+	// m_socket->Send(packet);
         
-        // ScheduleStartEvent();
-    }
+	// ScheduleStartEvent();
+}
 
-//}
 }
diff --git a/apps/stupid-interest-generator.h b/apps/stupid-interest-generator.h
index 395bc3f..f4fb287 100644
--- a/apps/stupid-interest-generator.h
+++ b/apps/stupid-interest-generator.h
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 //
 //  ndn_stupidinterestgenerator.h
 //  Abstraction
@@ -19,7 +20,6 @@
 namespace ns3 
 {
 
-    
 //namespace NDNabstraction
 //{
     class Socket; //dynamic linking works in a somehow strange way
diff --git a/apps/stupid-interest-sink.cc b/apps/stupid-interest-sink.cc
index febd621..c9b166e 100644
--- a/apps/stupid-interest-sink.cc
+++ b/apps/stupid-interest-sink.cc
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 //
 //  stupid-interest-sink.cpp
 //  Abstraction
diff --git a/apps/stupid-interest-sink.h b/apps/stupid-interest-sink.h
index 66cedd9..b750907 100644
--- a/apps/stupid-interest-sink.h
+++ b/apps/stupid-interest-sink.h
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 //
 //  stupid-interest-sink.h
 //  Abstraction
@@ -64,4 +65,4 @@
         TypeId          m_tid;          // Protocol TypeId
         TracedCallback<Ptr<const Packet>, const Address &> m_rxTrace;
     };
-}
\ No newline at end of file
+}
diff --git a/examples/ccnx-test.cc b/examples/ccnx-test.cc
new file mode 100644
index 0000000..4f4205c
--- /dev/null
+++ b/examples/ccnx-test.cc
@@ -0,0 +1,74 @@
+/* -*- 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/point-to-point-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/NDNabstraction-module.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("CcnxTest");
+
+int 
+main (int argc, char *argv[])
+{
+  Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (210));
+  Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("448kb/s"));
+  
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+  
+  // Here, we will explicitly create seven nodes. 
+  NodeContainer c;
+  c.Create (2);
+  
+  NodeContainer n = NodeContainer (c.Get (0), c.Get (2));
+  
+  // Ipv4StaticRoutingHelper staticRouting;
+  
+  // Ipv4ListRoutingHelper list;
+  // list.Add (staticRouting, 1);
+
+  CcnxStackHelper ccnx;
+  ccnx.Install (c);
+  
+  //Add static routing
+  // InternetStackHelper internet;
+  // internet.SetRoutingHelper (list); // has effect on the next Install ()
+  // internet.Install (c);
+  
+  // We create the channels first without any IP addressing information
+  // NS_LOG_INFO ("Create channels.");
+  // PointToPointHelper p2p;
+  // p2p.SetDeviceAttribute ("DataRate", StringValue ("10Mbps"));
+  // p2p.SetChannelAttribute ("Delay", StringValue ("1ms"));
+  // NetDeviceContainer nd = p2p.Install (n);
+  
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s from n0 to n4
+  NS_LOG_INFO ("Create Applications.");
+  
+  // std::string sendsizeattr = "SendSize";
+  // //flow2 7-->2
+  // BulkSendHelper bulksend0 ("ns3::CcnxLocalFaceFactory", InetSocketAddress (i23.GetAddress (0), port));
+  // //bulksend0.SetAttribute(sendsizeattr, AttributeValue(ConstantVariable(2560)));
+  // bulksend0.SetAttribute("MaxBytes", UintegerValue(2560));
+  // ApplicationContainer apps = bulksend0.Install(c.Get(6));
+  // apps.Start(Seconds (1.0));
+  // apps.Stop(Seconds (10.0));
+
+  // AsciiTraceHelper ascii;
+  // p2p.EnableAsciiAll (ascii.CreateFileStream ("ccnx-test.tr"));
+  // p2p.EnablePcapAll ("ccnx-test");
+  
+  Simulator::Stop (Seconds (20));
+  
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Run ();
+  Simulator::Destroy ();
+  NS_LOG_INFO ("Done.");
+  
+	return 0;
+}
diff --git a/examples/syntactic-topology-ndnabstraction.cc b/examples/syntactic-topology-ndnabstraction.cc
index c400fff..a1a92a1 100644
--- a/examples/syntactic-topology-ndnabstraction.cc
+++ b/examples/syntactic-topology-ndnabstraction.cc
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; c-set-offset 'innamespace 0; -*- */
 /*
  *  sync-topology-ndnabstraction.cpp
  *  XcodeProject
diff --git a/helper/ccnx-face-container.cc b/helper/ccnx-face-container.cc
new file mode 100644
index 0000000..f25ea5e
--- /dev/null
+++ b/helper/ccnx-face-container.cc
@@ -0,0 +1,81 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#include "ccnx-face-container.h"
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+
+namespace ns3 {
+
+CcnxFaceContainer::CcnxFaceContainer ()
+{
+}
+
+void
+CcnxFaceContainer::Add (CcnxFaceContainer other)
+{
+  for (FaceVector::const_iterator i = other.m_faces.begin (); i != other.m_faces.end (); i++)
+    {
+      m_faces.push_back (*i);
+    }
+}
+
+CcnxFaceContainer::Iterator
+CcnxFaceContainer::Begin (void) const
+{
+  return m_faces.begin ();
+}
+
+CcnxFaceContainer::Iterator
+CcnxFaceContainer::End (void) const
+{
+  return m_faces.end ();
+}
+
+uint32_t
+CcnxFaceContainer::GetN (void) const
+{
+  return m_faces.size ();
+}
+
+// CcnxAddress
+// CcnxFaceContainer::GetAddress (uint32_t i, uint32_t j) const
+// {
+//   Ptr<Ccnx> ccnx = m_faces[i].first;
+//   uint32_t face = m_faces[i].second;
+//   return ccnx->GetAddress (face, j).GetLocal ();
+// }
+
+void 
+CcnxFaceContainer::SetMetric (uint32_t i, uint16_t metric)
+{
+  Ptr<Ccnx> ccnx = m_faces[i].first;
+  uint32_t face = m_faces[i].second;
+  ccnx->SetMetric (face, metric);
+}
+
+void 
+CcnxFaceContainer::Add (Ptr<Ccnx> ccnx, uint32_t face)
+{
+  m_faces.push_back (std::make_pair (ccnx, face));
+}
+
+void CcnxFaceContainer::Add (std::pair<Ptr<Ccnx>, uint32_t> a)
+{
+  Add (a.first, a.second);
+}
+
+void 
+CcnxFaceContainer::Add (std::string ccnxName, uint32_t face)
+{
+  Ptr<Ccnx> ccnx = Names::Find<Ccnx> (ccnxName);
+  m_faces.push_back (std::make_pair (ccnx, face));
+}
+
+std::pair<Ptr<Ccnx>, uint32_t>
+CcnxFaceContainer::Get (uint32_t i) const
+{
+  return m_faces[i];
+}
+
+
+} // namespace ns3
diff --git a/helper/ccnx-face-container.h b/helper/ccnx-face-container.h
new file mode 100644
index 0000000..8bbbbc3
--- /dev/null
+++ b/helper/ccnx-face-container.h
@@ -0,0 +1,181 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+
+#ifndef CCNX_FACE_CONTAINER_H
+#define CCNX_FACE_CONTAINER_H
+
+#include <stdint.h>
+#include <vector>
+#include "ns3/ccnx.h"
+
+namespace ns3 {
+
+/**
+ * \brief holds a vector of std::pair of Ptr<Ccnx> and face index.
+ *
+ * Typically ns-3 CcnxFaces are installed on devices using an Ccnx address
+ * helper.  The helper's Assign() method takes a NetDeviceContainer which holds 
+ * some number of Ptr<NetDevice>.  For each of the NetDevices in the 
+ * NetDeviceContainer the helper will find the associated Ptr<Node> and
+ * Ptr<Ccnx>.  It makes sure that an face exists on the node for the 
+ * device and then adds an CcnxAddress according to the address helper settings
+ * (incrementing the CcnxAddress somehow as it goes).  The helper then converts
+ * the Ptr<Ccnx> and the face index to a std::pair and adds them to a 
+ * container -- a container of this type.
+ *
+ * The point is then to be able to implicitly associate an index into the 
+ * original NetDeviceContainer (that identifies a particular net device) with
+ * an identical index into the CcnxFaceContainer that has a std::pair with
+ * the Ptr<Ccnx> and face index you need to play with the face.
+ *
+ * @see CcnxAddressHelper
+ * @see Ccnx
+ */
+class CcnxFaceContainer
+{
+public:
+  typedef std::vector<std::pair<Ptr<Ccnx>, uint32_t> >::const_iterator Iterator;
+
+  /**
+   * Create an empty CcnxFaceContainer.
+   */
+  CcnxFaceContainer ();
+
+  /**
+   * Concatenate the entries in the other container with ours.
+   * \param other container
+   */
+  void Add (CcnxFaceContainer other);
+
+  /**
+   * \brief Get an iterator which refers to the first pair in the 
+   * container.
+   *
+   * Pairs can be retrieved from the container in two ways.  First,
+   * directly by an index into the container, and second, using an iterator.
+   * This method is used in the iterator method and is typically used in a 
+   * for-loop to run through the pairs
+   *
+   * \code
+   *   ccnxFaceContainer::Iterator i;
+   *   for (i = container.Begin (); i != container.End (); ++i)
+   *     {
+   *       std::pair<Ptr<Ccnx>, uint32_t> pair = *i;
+   *       method (pair.first, pair.second);  // use the pair
+   *     }
+   * \endcode
+   *
+   * \returns an iterator which refers to the first pair in the container.
+   */
+  Iterator Begin (void) const;
+
+  /**
+   * \brief Get an iterator which indicates past-the-last Node in the 
+   * container.
+   *
+   * Nodes can be retrieved from the container in two ways.  First,
+   * directly by an index into the container, and second, using an iterator.
+   * This method is used in the iterator method and is typically used in a 
+   * for-loop to run through the Nodes
+   *
+   * \code
+   *   NodeContainer::Iterator i;
+   *   for (i = container.Begin (); i != container.End (); ++i)
+   *     {
+   *       std::pair<Ptr<Ccnx>, uint32_t> pair = *i;
+   *       method (pair.first, pair.second);  // use the pair
+   *     }
+   * \endcode
+   *
+   * \returns an iterator which indicates an ending condition for a loop.
+   */
+  Iterator End (void) const;
+
+  /**
+   * \returns the number of Ptr<Ccnx> and face pairs stored in this 
+   * ccnxFaceContainer.
+   *
+   * Pairs can be retrieved from the container in two ways.  First,
+   * directly by an index into the container, and second, using an iterator.
+   * This method is used in the direct method and is typically used to
+   * define an ending condition in a for-loop that runs through the stored
+   * Nodes
+   *
+   * \code
+   *   uint32_t nNodes = container.GetN ();
+   *   for (uint32_t i = 0 i < nNodes; ++i)
+   *     {
+   *       std::pair<Ptr<Ccnx>, uint32_t> pair = container.Get (i);
+   *       method (pair.first, pair.second);  // use the pair
+   *     }
+   * \endcode
+   *
+   * \returns the number of Ptr<Node> stored in this container.
+   */
+  uint32_t GetN (void) const;
+
+  /**
+   * \param i index of ipfacePair in container
+   * \param j face address index (if face has multiple addresses)
+   * \returns the ccnx address of the j'th address of the face
+   *  corresponding to index i.
+   * 
+   * If the second parameter is omitted, the zeroth indexed address of 
+   * the face is returned.  Unless IP aliasing is being used on
+   * the face, the second parameter may typically be omitted.
+   */
+  // ccnxAddress GetAddress (uint32_t i, uint32_t j = 0) const;
+
+  void SetMetric (uint32_t i, uint16_t metric);
+
+  /**
+   * Manually add an entry to the container consisting of the individual parts
+   * of an entry std::pair.
+   *
+   * \param ccnx pointer to ccnx object
+   * \param face face index of the ccnxface to add to the container
+   *
+   * @see ccnxfaceContainer
+   */
+  void Add (Ptr<Ccnx> ccnx, uint32_t face);
+
+  /**
+   * Manually add an entry to the container consisting of a previously composed 
+   * entry std::pair.
+   *
+   * \param ipfacePair the pair of a pointer to ccnx object and face index of the ccnxface to add to the container
+   *
+   * @see ccnxfaceContainer
+   */
+  void Add (std::pair<Ptr<Ccnx>, uint32_t> ipFacePair);
+
+  /**
+   * Manually add an entry to the container consisting of the individual parts
+   * of an entry std::pair.
+   *
+   * \param ccnxName std:string referring to the saved name of an ccnx Object that
+   *        has been previously named using the Object Name Service.
+   * \param face face index of the ccnxface to add to the container
+   *
+   * @see ccnxfaceContainer
+   */
+  void Add (std::string ccnxName, uint32_t face);
+
+  /**
+   * Get the std::pair of an Ptr<Ccnx> and face stored at the location 
+   * specified by the index.
+   *
+   * \param i the index of the entery to retrieve.
+   *
+   * @see ccnxfaceContainer
+   */
+  std::pair<Ptr<Ccnx>, uint32_t> Get (uint32_t i) const;
+
+private:
+
+  typedef std::vector<std::pair<Ptr<Ccnx>,uint32_t> > FaceVector;
+  FaceVector m_faces;
+};
+
+} // namespace ns3
+
+#endif /* CCNX_FACE_CONTAINER_H */
diff --git a/helper/ccnx-forwarding-helper.cc b/helper/ccnx-forwarding-helper.cc
new file mode 100644
index 0000000..ed038cb
--- /dev/null
+++ b/helper/ccnx-forwarding-helper.cc
@@ -0,0 +1,83 @@
+/* -*- 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/node.h"
+#include "ns3/node-list.h"
+#include "ns3/simulator.h"
+#include "ns3/ccnx-forwarding-protocol.h"
+#include "ccnx-forwarding-helper.h"
+
+namespace ns3 {
+
+CcnxForwardingHelper::~CcnxForwardingHelper ()
+{
+}
+
+void
+CcnxForwardingHelper::PrintForwardingTableAllAt (Time printTime, Ptr<OutputStreamWrapper> stream) const
+{
+  for (uint32_t i = 0; i < NodeList::GetNNodes (); i++)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Simulator::Schedule (printTime, &CcnxForwardingHelper::Print, this, node, stream);
+    }
+}
+
+void
+CcnxForwardingHelper::PrintForwardingTableAllEvery (Time printInterval, Ptr<OutputStreamWrapper> stream) const
+{
+  for (uint32_t i = 0; i < NodeList::GetNNodes (); i++)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Simulator::Schedule (printInterval, &CcnxForwardingHelper::PrintEvery, this, printInterval, node, stream);
+    }
+}
+
+void
+CcnxForwardingHelper::PrintForwardingTableAt (Time printTime, Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const
+{
+  Simulator::Schedule (printTime, &CcnxForwardingHelper::Print, this, node, stream);
+}
+
+void
+CcnxForwardingHelper::PrintForwardingTableEvery (Time printInterval,Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const
+{
+  Simulator::Schedule (printInterval, &CcnxForwardingHelper::PrintEvery, this, printInterval, node, stream);
+}
+
+void
+CcnxForwardingHelper::Print (Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const
+{
+  Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+  Ptr<CcnxForwardingProtocol> rp = ccnx->GetForwardingProtocol ();
+  NS_ASSERT (rp);
+  rp->PrintForwardingTable (stream);
+}
+
+void
+CcnxForwardingHelper::PrintEvery (Time printInterval, Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const
+{
+  Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+  Ptr<CcnxForwardingProtocol> rp = ccnx->GetForwardingProtocol ();
+  NS_ASSERT (rp);
+  rp->PrintForwardingTable (stream);
+  Simulator::Schedule (printInterval, &CcnxForwardingHelper::PrintEvery, this, printInterval, node, stream);
+}
+
+} // namespace ns3
diff --git a/helper/ccnx-forwarding-helper.h b/helper/ccnx-forwarding-helper.h
new file mode 100644
index 0000000..d66584f
--- /dev/null
+++ b/helper/ccnx-forwarding-helper.h
@@ -0,0 +1,118 @@
+/* -*- 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 CCNX_FORWARDING_HELPER_H
+#define CCNX_FORWARDING_HELPER_H
+
+#include "ns3/ptr.h"
+#include "ns3/nstime.h"
+#include "ns3/output-stream-wrapper.h"
+
+namespace ns3 {
+
+class CcnxForwardingProtocol;
+class Node;
+
+/**
+ * \brief a factory to create ns3::CcnxForwardingProtocol objects
+ *
+ * For each new forwarding protocol created as a subclass of 
+ * ns3::CcnxForwardingProtocol, you need to create a subclass of 
+ * ns3::CcnxForwardingHelper which can be used by 
+ * ns3::InternetStackHelper::SetForwardingHelper and 
+ * ns3::InternetStackHelper::Install.
+ */
+class CcnxForwardingHelper
+{
+public:
+  /*
+   * Destroy an instance of an CcnxForwardingHelper
+   */
+  virtual ~CcnxForwardingHelper ();
+
+  /**
+   * \brief virtual constructor
+   * \returns pointer to clone of this CcnxForwardingHelper 
+   * 
+   * This method is mainly for internal use by the other helpers;
+   * clients are expected to free the dynamic memory allocated by this method
+   */
+  virtual CcnxForwardingHelper* Copy (void) const = 0;
+
+  /**
+   * \param node the node within which the new forwarding protocol will run
+   * \returns a newly-created forwarding protocol
+   */
+  virtual Ptr<CcnxForwardingProtocol> Create (Ptr<Node> node) const = 0;
+
+  /**
+   * \brief prints the forwarding tables of all nodes at a particular time.
+   * \param printTime the time at which the forwarding table is supposed to be printed.
+   * \param stream The output stream object to use 
+   *
+   * This method calls the PrintForwardingTable() method of the 
+   * CcnxForwardingProtocol stored in the Ccnx object, for all nodes at the
+   * specified time; the output format is forwarding protocol-specific.
+   */
+  void PrintForwardingTableAllAt (Time printTime, Ptr<OutputStreamWrapper> stream) const;
+
+  /**
+   * \brief prints the forwarding tables of all nodes at regular intervals specified by user.
+   * \param printInterval the time interval for which the forwarding table is supposed to be printed.
+   * \param stream The output stream object to use
+   *
+   * This method calls the PrintForwardingTable() method of the 
+   * CcnxForwardingProtocol stored in the Ccnx object, for all nodes at the
+   * specified time interval; the output format is forwarding protocol-specific.
+   */
+  void PrintForwardingTableAllEvery (Time printInterval, Ptr<OutputStreamWrapper> stream) const;
+
+  /**
+   * \brief prints the forwarding tables of a node at a particular time.
+   * \param printTime the time at which the forwarding table is supposed to be printed.
+   * \param node The node ptr for which we need the forwarding table to be printed
+   * \param stream The output stream object to use
+   *
+   * This method calls the PrintForwardingTable() method of the 
+   * CcnxForwardingProtocol stored in the Ccnx object, for the selected node 
+   * at the specified time; the output format is forwarding protocol-specific.
+   */
+  void PrintForwardingTableAt (Time printTime, Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const;
+
+  /**
+   * \brief prints the forwarding tables of a node at regular intervals specified by user.
+   * \param printInterval the time interval for which the forwarding table is supposed to be printed.
+   * \param node The node ptr for which we need the forwarding table to be printed
+   * \param stream The output stream object to use
+   *
+   * This method calls the PrintForwardingTable() method of the 
+   * CcnxForwardingProtocol stored in the Ccnx object, for the selected node 
+   * at the specified interval; the output format is forwarding protocol-specific.
+   */
+  void PrintForwardingTableEvery (Time printInterval, Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const;
+
+private:
+  void Print (Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const;
+  void PrintEvery (Time printInterval, Ptr<Node> node, Ptr<OutputStreamWrapper> stream) const;
+};
+
+} // namespace ns3
+
+
+#endif /* CCNX_FORWARDING_HELPER_H */
diff --git a/helper/ccnx-stack-helper.cc b/helper/ccnx-stack-helper.cc
new file mode 100644
index 0000000..836c379
--- /dev/null
+++ b/helper/ccnx-stack-helper.cc
@@ -0,0 +1,494 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 UCLA
+ *
+ * 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: 
+ */
+
+/**
+ * \ingroup ccnx
+ * \defgroup CcnxStackModel Ccnx Stack Model
+ *
+ * \section CcnxStackTracingModel Tracing in the Ccnx Stack
+ *
+ * The ccnx stack provides a number of trace sources in its various
+ * protocol implementations.  These trace sources can be hooked using your own 
+ * custom trace code, or you can use our helper functions in some cases to 
+ * arrange for tracing to be enabled.
+ *
+ * \subsection CcnxStackCcnxTracingModel Tracing in Ccnx
+ *
+ * The Ccnx layer three protocol provides three trace hooks.  These are the 
+ * "Tx" (ns3::CcnxL3Protocol::m_txTrace), "Rx" (ns3::CcnxL3Protocol::m_rxTrace) 
+ * and "Drop" (ns3::CcnxL3Protocol::m_dropTrace) trace sources.
+ *
+ * The "Tx" trace is fired in a number of situations, all of which indicate that
+ * a given packet is about to be sent down to a given ns3::CcnxFace.
+ *
+ * - \todo list Tx trace events
+ *
+ * The "Rx" trace is fired when a packet is passed from the device up to the
+ * ns3::CcnxL3Protocol::Receive function.
+ *
+ * - In the receive function, the CcnxFaceList is iterated, and if the
+ *   CcnxFace corresponding to the receiving device is found to be in the
+ *   UP state, the trace is fired.
+ *
+ * The "Drop" trace is fired in any case where the packet is dropped (in both
+ * the transmit and receive paths).
+ *
+ * - \todo list Drop trace events
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/object.h"
+#include "ns3/names.h"
+#include "ns3/ccnx.h"
+#include "ns3/packet-socket-factory.h"
+#include "ns3/config.h"
+#include "ns3/simulator.h"
+#include "ns3/string.h"
+#include "ns3/net-device.h"
+#include "ns3/callback.h"
+#include "ns3/node.h"
+#include "ns3/core-config.h"
+#include "ns3/ccnx-forwarding-protocol.h"
+
+#include "ccnx-stack-helper.h"
+#include "ccnx-forwarding-helper.h"
+
+#include <limits>
+#include <map>
+
+NS_LOG_COMPONENT_DEFINE ("CcnxStackHelper");
+
+namespace ns3 {
+
+// Things are going to work differently here with respect to trace
+// file handling than in most places because the Tx and Rx trace
+// sources we are interested in are going to multiplex receive and
+// transmit callbacks for all Ccnx and face pairs through one
+// callback.  We want packets to or from each distinct pair to go to
+// an individual file, so we have got to demultiplex the Ccnx and face
+// pair into a corresponding Ptr<PcapFileWrapper> at the callback.
+//
+// A complication in this situation is that the trace sources are
+// hooked on a protocol basis.  There is no trace source hooked by an
+// Ccnx and face pair.  This means that if we naively proceed to hook,
+// say, a drop trace for a given Ccnx with face 0, and then hook for
+// Ccnx with face 1 we will hook the drop trace twice and get two
+// callbacks per event.  What we need to do is to hook the event once,
+// and that will result in a single callback per drop event, and the
+// trace source will provide the face which we filter on in the trace
+// sink.
+// 
+// This has got to continue to work properly after the helper has been
+// destroyed; but must be cleaned up at the end of time to avoid
+// leaks.  Global maps of protocol/face pairs to file objects seems to
+// fit the bill.
+//
+typedef std::pair<Ptr<Ccnx>, uint32_t> FacePairCcnx; 
+typedef std::map<FacePairCcnx, Ptr<PcapFileWrapper> > FaceFileMapCcnx;
+typedef std::map<FacePairCcnx, Ptr<OutputStreamWrapper> > FaceStreamMapCcnx;
+
+static FaceFileMapCcnx g_faceFileMapCcnx; /**< A mapping of Ccnx/face pairs to pcap files */
+static FaceStreamMapCcnx g_faceStreamMapCcnx; /**< A mapping of Ccnx/face pairs to ascii streams */
+
+CcnxStackHelper::CcnxStackHelper ()
+  : m_forwarding (0)
+  , m_ccnxEnabled (true)
+{
+  Initialize ();
+}
+
+// private method called by both constructor and Reset ()
+void
+CcnxStackHelper::Initialize ()
+{
+  // CcnxStaticForwardingHelper staticForwarding;
+  // CcnxGlobalForwardingHelper globalForwarding;
+  // CcnxListForwardingHelper listForwarding;
+  // listForwarding.Add (staticForwarding, 0);
+  // listForwarding.Add (globalForwarding, -10);
+  // SetForwardingHelper (listForwarding);
+}
+
+CcnxStackHelper::~CcnxStackHelper ()
+{
+  if (m_forwarding)
+    {
+      delete m_forwarding;
+      m_forwarding = 0;
+    }
+}
+
+CcnxStackHelper::CcnxStackHelper (const CcnxStackHelper &o)
+{
+  m_forwarding = o.m_forwarding->Copy ();
+  m_ccnxEnabled = o.m_ccnxEnabled;
+}
+
+CcnxStackHelper &
+CcnxStackHelper::operator = (const CcnxStackHelper &o)
+{
+  if (this == &o)
+    {
+      return *this;
+    }
+  m_forwarding = o.m_forwarding->Copy ();
+  return *this;
+}
+
+void
+CcnxStackHelper::Reset (void)
+{
+  delete m_forwarding;
+  m_forwarding = 0;
+  m_ccnxEnabled = true;
+  Initialize ();
+}
+
+void 
+CcnxStackHelper::SetForwardingHelper (const CcnxForwardingHelper &forwarding)
+{
+  delete m_forwarding;
+  m_forwarding = forwarding.Copy ();
+}
+
+void
+CcnxStackHelper::SetCcnxStackInstall (bool enable)
+{
+  m_ccnxEnabled = enable;
+}
+
+void 
+CcnxStackHelper::Install (NodeContainer c) const
+{
+  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      Install (*i);
+    }
+}
+
+void 
+CcnxStackHelper::InstallAll (void) const
+{
+  Install (NodeContainer::GetGlobal ());
+}
+
+void
+CcnxStackHelper::CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId)
+{
+  ObjectFactory factory;
+  factory.SetTypeId (typeId);
+  Ptr<Object> protocol = factory.Create <Object> ();
+  node->AggregateObject (protocol);
+}
+
+void
+CcnxStackHelper::Install (Ptr<Node> node) const
+{
+  NS_ASSERT_MSG (m_forwarding, "CcnxForwarding should be set prior calling Install() method");
+  
+  if (m_ccnxEnabled)
+    {
+      if (node->GetObject<Ccnx> () != 0)
+        {
+          NS_FATAL_ERROR ("CcnxStackHelper::Install (): Installing " 
+                          "a CcnxStack to a node with an existing Ccnx object");
+          return;
+        }
+
+      CreateAndAggregateObjectFromTypeId (node, "ns3::CcnxL3Protocol");
+      // Set forwarding
+      Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+      Ptr<CcnxForwardingProtocol> ccnxForwarding = m_forwarding->Create (node);
+      ccnx->SetForwardingProtocol (ccnxForwarding);
+    }
+}
+
+void
+CcnxStackHelper::Install (std::string nodeName) const
+{
+  Ptr<Node> node = Names::Find<Node> (nodeName);
+  Install (node);
+}
+
+static void
+CcnxL3ProtocolRxTxSink (Ptr<const Packet> p, Ptr<Ccnx> ccnx, uint32_t face)
+{
+  NS_LOG_FUNCTION (p << ccnx << face);
+
+  //
+  // Since trace sources are independent of face, if we hook a source
+  // on a particular protocol we will get traces for all of its faces.
+  // We need to filter this to only report faces for which the user 
+  // has expressed interest.
+  //
+  FacePairCcnx pair = std::make_pair (ccnx, face);
+  if (g_faceFileMapCcnx.find (pair) == g_faceFileMapCcnx.end ())
+    {
+      NS_LOG_INFO ("Ignoring packet to/from face " << face);
+      return;
+    }
+
+  Ptr<PcapFileWrapper> file = g_faceFileMapCcnx[pair];
+  file->Write (Simulator::Now (), p);
+}
+
+bool
+CcnxStackHelper::PcapHooked (Ptr<Ccnx> ccnx)
+{
+  for (FaceFileMapCcnx::const_iterator i = g_faceFileMapCcnx.begin (); 
+       i != g_faceFileMapCcnx.end (); 
+       ++i)
+    {
+      if ((*i).first.first == ccnx)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+void 
+CcnxStackHelper::EnablePcapCcnxInternal (std::string prefix, Ptr<Ccnx> ccnx, uint32_t face, bool explicitFilename)
+{
+  NS_LOG_FUNCTION (prefix << ccnx << face);
+
+  if (!m_ccnxEnabled)
+    {
+      NS_LOG_INFO ("Call to enable Ccnx pcap tracing but Ccnx not enabled");
+      return;
+    }
+
+  //
+  // We have to create a file and a mapping from protocol/face to file 
+  // irrespective of how many times we want to trace a particular protocol.
+  //
+  PcapHelper pcapHelper;
+
+  std::string filename;
+  if (explicitFilename)
+    {
+      filename = prefix;
+    }
+  else
+    {
+      filename = pcapHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
+    }
+
+  Ptr<PcapFileWrapper> file = pcapHelper.CreateFile (filename, std::ios::out, PcapHelper::DLT_RAW);
+
+  //
+  // However, we only hook the trace source once to avoid multiple trace sink
+  // calls per event (connect is independent of face).
+  //
+  if (!PcapHooked (ccnx))
+    {
+      //
+      // Ptr<Ccnx> is aggregated to node and CcnxL3Protocol is aggregated to 
+      // node so we can get to CcnxL3Protocol through Ccnx.
+      //
+      Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
+      NS_ASSERT_MSG (ccnxL3Protocol, "CcnxStackHelper::EnablePcapCcnxInternal(): "
+                     "m_ccnxEnabled and ccnxL3Protocol inconsistent");
+
+      bool result = ccnxL3Protocol->TraceConnectWithoutContext ("Tx", MakeCallback (&CcnxL3ProtocolRxTxSink));
+      NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal():  "
+                     "Unable to connect ccnxL3Protocol \"Tx\"");
+
+      result = ccnxL3Protocol->TraceConnectWithoutContext ("Rx", MakeCallback (&CcnxL3ProtocolRxTxSink));
+      NS_ASSERT_MSG (result == true, "CcnxStackHelper::EnablePcapCcnxInternal():  "
+                     "Unable to connect ccnxL3Protocol \"Rx\"");
+      // cast result to void, to suppress ‘result’ set but not used compiler-warning
+      // for optimized builds
+      (void) result;
+    }
+
+  g_faceFileMapCcnx[std::make_pair (ccnx, face)] = file;
+}
+
+static void
+CcnxL3ProtocolDropSinkWithoutContext (
+  Ptr<OutputStreamWrapper> stream,
+  Ptr<const Packet> packet,
+  CcnxL3Protocol::DropReason reason, 
+  Ptr<Ccnx> ccnx, 
+  uint32_t face)
+{
+  //
+  // Since trace sources are independent of face, if we hook a source
+  // on a particular protocol we will get traces for all of its faces.
+  // We need to filter this to only report faces for which the user 
+  // has expressed interest.
+  //
+  FacePairCcnx pair = std::make_pair (ccnx, face);
+  if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
+    {
+      NS_LOG_INFO ("Ignoring packet to/from face " << face);
+      return;
+    }
+
+  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *packet << std::endl;
+}
+
+static void
+CcnxL3ProtocolDropSinkWithContext (
+  Ptr<OutputStreamWrapper> stream,
+  std::string context,
+  Ptr<const Packet> packet,
+  CcnxL3Protocol::DropReason reason, 
+  Ptr<Ccnx> ccnx, 
+  uint32_t face)
+{
+  //
+  // Since trace sources are independent of face, if we hook a source
+  // on a particular protocol we will get traces for all of its faces.
+  // We need to filter this to only report faces for which the user 
+  // has expressed interest.
+  //
+  FacePairCcnx pair = std::make_pair (ccnx, face);
+  if (g_faceStreamMapCcnx.find (pair) == g_faceStreamMapCcnx.end ())
+    {
+      NS_LOG_INFO ("Ignoring packet to/from face " << face);
+      return;
+    }
+
+  *stream->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << "(" << face << ") " 
+                        << *packet << std::endl;
+}
+
+bool
+CcnxStackHelper::AsciiHooked (Ptr<Ccnx> ccnx)
+{
+  for (  FaceStreamMapCcnx::const_iterator i = g_faceStreamMapCcnx.begin (); 
+         i != g_faceStreamMapCcnx.end (); 
+         ++i)
+    {
+      if ((*i).first.first == ccnx)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+void 
+CcnxStackHelper::EnableAsciiCcnxInternal (
+  Ptr<OutputStreamWrapper> stream, 
+  std::string prefix, 
+  Ptr<Ccnx> ccnx, 
+  uint32_t face,
+  bool explicitFilename)
+{
+  if (!m_ccnxEnabled)
+    {
+      NS_LOG_INFO ("Call to enable Ccnx ascii tracing but Ccnx not enabled");
+      return;
+    }
+
+  //
+  // Our 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 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.
+      //
+      // We have to create a stream and a mapping from protocol/face to 
+      // stream irrespective of how many times we want to trace a particular 
+      // protocol.
+      //
+      AsciiTraceHelper asciiTraceHelper;
+
+      std::string filename;
+      if (explicitFilename)
+        {
+          filename = prefix;
+        }
+      else
+        {
+          filename = asciiTraceHelper.GetFilenameFromInterfacePair (prefix, ccnx, face);
+        }
+
+      Ptr<OutputStreamWrapper> theStream = asciiTraceHelper.CreateFileStream (filename);
+
+      //
+      // However, we only hook the trace sources once to avoid multiple trace sink
+      // calls per event (connect is independent of face).
+      //
+      if (!AsciiHooked (ccnx))
+        {
+          //
+          // The drop sink for the CcnxL3Protocol uses a different signature than
+          // the default sink, so we have to cook one up for ourselves.  We can get
+          // to the Ptr<CcnxL3Protocol> through our Ptr<Ccnx> since they must both 
+          // be aggregated to the same node.
+          //
+          Ptr<CcnxL3Protocol> ccnxL3Protocol = ccnx->GetObject<CcnxL3Protocol> ();
+          bool __attribute__ ((unused)) result = ccnxL3Protocol->TraceConnectWithoutContext ("Drop", 
+                                                                                             MakeBoundCallback (&CcnxL3ProtocolDropSinkWithoutContext, theStream));
+          NS_ASSERT_MSG (result == true, "CcnxStackHelper::EanableAsciiCcnxInternal():  "
+                         "Unable to connect ccnxL3Protocol \"Drop\"");
+        }
+
+      g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = theStream;
+      return;
+    }
+
+  //
+  // If we are provided an OutputStreamWrapper, we are expected to use it, and
+  // to provide 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.
+  //
+  // We need to associate the ccnx/face with a stream to express interest
+  // in tracing events on that pair, however, we only hook the trace sources 
+  // once to avoid multiple trace sink calls per event (connect is independent
+  // of face).
+  //
+  if (!AsciiHooked (ccnx))
+    {
+      Ptr<Node> node = ccnx->GetObject<Node> ();
+      std::ostringstream oss;
+
+      //
+      // This has all kinds of parameters coming with, so we have to cook up our
+      // own sink.
+      //
+      oss.str ("");
+      oss << "/NodeList/" << node->GetId () << "/$ns3::CcnxL3Protocol/Drop";
+      Config::Connect (oss.str (), MakeBoundCallback (&CcnxL3ProtocolDropSinkWithContext, stream));
+    }
+
+  g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
+}
+
+} // namespace ns3
diff --git a/helper/ccnx-stack-helper.h b/helper/ccnx-stack-helper.h
new file mode 100644
index 0000000..d692b05
--- /dev/null
+++ b/helper/ccnx-stack-helper.h
@@ -0,0 +1,191 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 UCLA
+ *
+ * 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: 
+ */
+
+#ifndef CCNX_STACK_HELPER_H
+#define CCNX_STACK_HELPER_H
+
+#include "ns3/node-container.h"
+#include "ns3/net-device-container.h"
+#include "ns3/packet.h"
+#include "ns3/ptr.h"
+#include "ns3/object-factory.h"
+#include "ns3/ccnx-l3-protocol.h"
+
+#include "ccnx-trace-helper.h"
+
+namespace ns3 {
+
+class Node;
+class CcnxForwardingHelper;
+
+/**
+ * \brief Adding CCNx functionality to existing Nodes.
+ *
+ * This helper enables pcap and ascii tracing of events in the ccnx stack
+ * associated with a node.  This is substantially similar to the tracing that
+ * happens in device helpers, but the important difference is that, well, there
+ * is no device.  This means that the creation of output file names will change,
+ * and also the user-visible methods will not reference devices and therefore
+ * the number of trace enable methods is reduced.
+ *
+ * Normally we eschew multiple inheritance, however, the classes
+ * PcapUserHelperForCcnx and AsciiTraceUserHelperForCcnx are treated as
+ * "mixins".  A mixin is a self-contained class that encapsulates a general
+ * attribute or a set of functionality that may be of interest to many other
+ * classes.
+ */
+class CcnxStackHelper : public PcapHelperForCcnx, public AsciiTraceHelperForCcnx
+{
+public:
+  /**
+   * Create a new CcnxStackHelper which <empty> forwarding by default.
+   *
+   * \todo set non-empty default forwarding
+   */
+  CcnxStackHelper ();
+
+  /**
+   * Destroy the CcnxStackHelper
+   */
+  virtual ~CcnxStackHelper ();
+  CcnxStackHelper (const CcnxStackHelper &);
+  CcnxStackHelper &operator = (const CcnxStackHelper &o);
+
+  /**
+   * Return helper internal state to that of a newly constructed one
+   */
+  void Reset ();
+
+  /**
+   * \param forwarding a new forwarding helper
+   *
+   * Set the forwarding helper to use during Install. The forwarding helper is
+   * really an object factory which is used to create an object of type
+   * ns3::CcnxFrProtocol per node. This forwarding object is then associated to
+   * a single ns3::Ccnx object through its ns3::Ccnx::SetforwardingProtocol.
+   */
+  void SetForwardingHelper (const CcnxForwardingHelper &forwarding);
+
+  /**
+   * Install CCNx stack on the node
+   *
+   * This method will assert if called on a node that already has Ccnx object
+   * installed on it
+   * 
+   * \param nodeName The name of the node on which to install the stack.
+   */
+  void Install (std::string nodeName) const;
+
+  /**
+   * Install CCNx stack on the node
+   *
+   * This method will assert if called on a node that already has Ccnx object
+   * installed on it
+   * 
+   * \param node The node on which to install the stack.
+   */
+  void Install (Ptr<Node> node) const;
+
+  /**
+   * Install CCNx stack on each node in the input container
+   *
+   * The program will assert if this method is called on a container with a node
+   * that already has an ccnx object aggregated to it.
+   * 
+   * \param c NodeContainer that holds the set of nodes on which to install the
+   * new stacks.
+   */
+  void Install (NodeContainer c) const;
+
+  /**
+   * Install CCNx stack on all nodes in the simulation
+   */
+  void 
+  InstallAll () const;
+
+  /**
+   * \brief Enable/disable ccnx stack install.
+   * \param enable enable state
+   */
+  void SetCcnxStackInstall (bool enable);
+
+private:
+  /**
+   * @brief Enable pcap output the indicated Ccnx and interface pair.
+   * @internal
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param ccnx Ptr to the Ccnx interface on which you want to enable tracing.
+   * @param interface Interface ID on the Ccnx on which you want to enable tracing.
+   */
+  virtual void EnablePcapCcnxInternal (std::string prefix, 
+                                       Ptr<Ccnx> ccnx, 
+                                       uint32_t interface,
+                                       bool explicitFilename);
+
+  /**
+   * @brief Enable ascii trace output on the indicated Ccnx and interface pair.
+   * @internal
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param prefix Filename prefix to use for ascii trace files.
+   * @param ccnx Ptr to the Ccnx interface on which you want to enable tracing.
+   * @param interface Interface ID on the Ccnx on which you want to enable tracing.
+   */
+  virtual void EnableAsciiCcnxInternal (Ptr<OutputStreamWrapper> stream, 
+                                        std::string prefix, 
+                                        Ptr<Ccnx> ccnx, 
+                                        uint32_t interface,
+                                        bool explicitFilename);
+
+  void Initialize (void);
+  ObjectFactory m_tcpFactory;
+  const CcnxForwardingHelper *m_forwarding;
+
+  /**
+   * \internal
+   */
+  static void CreateAndAggregateObjectFromTypeId (Ptr<Node> node, const std::string typeId);
+
+  /**
+   * \internal
+   */
+  static void Cleanup (void);
+
+  /**
+   * \internal
+   */
+  bool PcapHooked (Ptr<Ccnx> ccnx);
+
+  /**
+   * \internal
+   */
+  bool AsciiHooked (Ptr<Ccnx> ccnx);
+
+  /**
+   * \brief Ccnx install state (enabled/disabled) ?
+   */
+  bool m_ccnxEnabled;
+};
+
+} // namespace ns3
+
+#endif /* CCNX_STACK_HELPER_H */
diff --git a/helper/ccnx-trace-helper.cc b/helper/ccnx-trace-helper.cc
new file mode 100644
index 0000000..4ee4e2f
--- /dev/null
+++ b/helper/ccnx-trace-helper.cc
@@ -0,0 +1,303 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2010 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 <stdint.h>
+#include <string>
+#include <fstream>
+
+#include "ns3/abort.h"
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/node.h"
+#include "ns3/names.h"
+#include "ns3/net-device.h"
+#include "ns3/pcap-file-wrapper.h"
+
+#include "ccnx-trace-helper.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxTraceHelper");
+
+namespace ns3 {
+
+void 
+PcapHelperForCcnx::EnablePcapCcnx (std::string prefix, Ptr<Ccnx> ccnx, uint32_t interface, bool explicitFilename)
+{
+  EnablePcapCcnxInternal (prefix, ccnx, interface, explicitFilename);
+}
+
+void 
+PcapHelperForCcnx::EnablePcapCcnx (std::string prefix, std::string ccnxName, uint32_t interface, bool explicitFilename)
+{
+  Ptr<Ccnx> ccnx = Names::Find<Ccnx> (ccnxName);
+  EnablePcapCcnx (prefix, ccnx, interface, explicitFilename);
+}
+
+void 
+PcapHelperForCcnx::EnablePcapCcnx (std::string prefix, CcnxFaceContainer c)
+{
+  for (CcnxFaceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      std::pair<Ptr<Ccnx>, uint32_t> pair = *i;
+      EnablePcapCcnx (prefix, pair.first, pair.second, false);
+    }
+}
+
+void
+PcapHelperForCcnx::EnablePcapCcnx (std::string prefix, NodeContainer n)
+{
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+      if (ccnx)
+        {
+          for (uint32_t j = 0; j < ccnx->GetNFaces (); ++j)
+            {
+              EnablePcapCcnx (prefix, ccnx, j, false);
+            }
+        }
+    }
+}
+
+void
+PcapHelperForCcnx::EnablePcapCcnxAll (std::string prefix)
+{
+  EnablePcapCcnx (prefix, NodeContainer::GetGlobal ());
+}
+
+void 
+PcapHelperForCcnx::EnablePcapCcnx (std::string prefix, uint32_t nodeid, uint32_t interface, bool explicitFilename)
+{
+  NodeContainer n = NodeContainer::GetGlobal ();
+
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      if (node->GetId () != nodeid) 
+        {
+          continue;
+        }
+
+      Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+      if (ccnx)
+        {
+          EnablePcapCcnx (prefix, ccnx, interface, explicitFilename);
+        }
+      return;
+    }
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (std::string prefix, Ptr<Ccnx> ccnx, uint32_t interface, bool explicitFilename)
+{
+  EnableAsciiCcnxInternal (Ptr<OutputStreamWrapper> (), prefix, ccnx, interface, explicitFilename);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, Ptr<Ccnx> ccnx, uint32_t interface)
+{
+  EnableAsciiCcnxInternal (stream, std::string (), ccnx, interface, false);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (
+  std::string prefix, 
+  std::string ccnxName, 
+  uint32_t interface,
+  bool explicitFilename)
+{
+  EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> (), prefix, ccnxName, interface, explicitFilename);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, std::string ccnxName, uint32_t interface)
+{
+  EnableAsciiCcnxImpl (stream, std::string (), ccnxName, interface, false);
+}
+
+//
+// Private API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnxImpl (
+  Ptr<OutputStreamWrapper> stream, 
+  std::string prefix, 
+  std::string ccnxName, 
+  uint32_t interface,
+  bool explicitFilename)
+{
+  Ptr<Ccnx> ccnx = Names::Find<Ccnx> (ccnxName);
+  EnableAsciiCcnxInternal (stream, prefix, ccnx, interface, explicitFilename);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (std::string prefix, CcnxFaceContainer c)
+{
+  EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> (), prefix, c);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, CcnxFaceContainer c)
+{
+  EnableAsciiCcnxImpl (stream, std::string (), c);
+}
+
+//
+// Private API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, CcnxFaceContainer c)
+{
+  for (CcnxFaceContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+    {
+      std::pair<Ptr<Ccnx>, uint32_t> pair = *i;
+      EnableAsciiCcnxInternal (stream, prefix, pair.first, pair.second, false);
+    }
+}
+
+//
+// Public API
+//
+void
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (std::string prefix, NodeContainer n)
+{
+  EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> (), prefix, n);
+}
+
+//
+// Public API
+//
+void
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, NodeContainer n)
+{
+  EnableAsciiCcnxImpl (stream, std::string (), n);
+}
+
+//
+// Private API
+//
+void
+AsciiTraceHelperForCcnx::EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, NodeContainer n)
+{
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+      if (ccnx)
+        {
+          for (uint32_t j = 0; j < ccnx->GetNFaces (); ++j)
+            {
+              EnableAsciiCcnxInternal (stream, prefix, ccnx, j, false);
+            }
+        }
+    }
+}
+
+//
+// Public API
+//
+void
+AsciiTraceHelperForCcnx::EnableAsciiCcnxAll (std::string prefix)
+{
+  EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> (), prefix, NodeContainer::GetGlobal ());
+}
+
+//
+// Public API
+//
+void
+AsciiTraceHelperForCcnx::EnableAsciiCcnxAll (Ptr<OutputStreamWrapper> stream)
+{
+  EnableAsciiCcnxImpl (stream, std::string (), NodeContainer::GetGlobal ());
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (
+  Ptr<OutputStreamWrapper> stream, 
+  uint32_t nodeid, 
+  uint32_t interface,
+  bool explicitFilename)
+{
+  EnableAsciiCcnxImpl (stream, std::string (), nodeid, interface, explicitFilename);
+}
+
+//
+// Public API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnx (std::string prefix, uint32_t nodeid, uint32_t interface, bool explicitFilename)
+{
+  EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> (), prefix, nodeid, interface, explicitFilename);
+}
+
+//
+// Private API
+//
+void 
+AsciiTraceHelperForCcnx::EnableAsciiCcnxImpl (
+  Ptr<OutputStreamWrapper> stream, 
+  std::string prefix, 
+  uint32_t nodeid, 
+  uint32_t interface,
+  bool explicitFilename)
+{
+  NodeContainer n = NodeContainer::GetGlobal ();
+
+  for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i)
+    {
+      Ptr<Node> node = *i;
+      if (node->GetId () != nodeid) 
+        {
+          continue;
+        }
+
+      Ptr<Ccnx> ccnx = node->GetObject<Ccnx> ();
+      if (ccnx)
+        {
+          EnableAsciiCcnxInternal (stream, prefix, ccnx, interface, explicitFilename);
+        }
+
+      return;
+    }
+}
+
+
+} // namespace ns3
+
diff --git a/helper/ccnx-trace-helper.h b/helper/ccnx-trace-helper.h
new file mode 100644
index 0000000..6c4fa7b
--- /dev/null
+++ b/helper/ccnx-trace-helper.h
@@ -0,0 +1,339 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 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_TRACE_HELPER_H
+#define CCNX_TRACE_HELPER_H
+
+#include "ns3/assert.h"
+#include "ns3/ccnx-face-container.h"
+#include "ns3/ccnx.h"
+#include "ns3/trace-helper.h"
+
+namespace ns3 {
+
+/**
+ * @brief Base class providing common user-level pcap operations for helpers
+ * representing Ccnx protocols .
+ */
+class PcapHelperForCcnx
+{
+public:
+  /**
+   * @brief Construct a PcapHelperForCcnx.
+   */
+  PcapHelperForCcnx () {}
+
+  /**
+   * @brief Destroy a PcapHelperForCcnx.
+   */
+  virtual ~PcapHelperForCcnx () {}
+
+  /**
+   * @brief Enable pcap output the indicated Ccnx and interface pair.
+   * @internal
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param Ccnx Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface Interface on Ccnx on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  virtual void EnablePcapCcnxInternal (std::string prefix, 
+                                       Ptr<Ccnx> ccnx, 
+                                       uint32_t interface,
+                                       bool explicitFilename) = 0;
+
+  /**
+   * @brief Enable pcap output the indicated Ccnx and interface pair.
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param ccnx Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface Interface on ccnx on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true.
+   */
+  void EnablePcapCcnx (std::string prefix, Ptr<Ccnx> ccnx, uint32_t interface, bool explicitFilename = false);
+
+  /**
+   * @brief Enable pcap output the indicated ccnx and interface pair using a
+   * Ptr<Ccnx> previously named using the ns-3 object name service.
+   *
+   * @param prefix filename prefix to use for pcap files.
+   * @param ccnxName Name of the Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface Interface on ccnx on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true.
+   */
+  void EnablePcapCcnx (std::string prefix, std::string ccnxName, uint32_t interface, bool explicitFilename = false);
+
+  /**
+   * @brief Enable pcap output on each Ccnx and interface pair in the container.
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param c CcnxFaceContainer of Ccnx and interface pairs
+   */
+  void EnablePcapCcnx (std::string prefix, CcnxFaceContainer c);
+
+  /**
+   * @brief Enable pcap output on all Ccnx and interface pairs existing in the
+   * nodes provided in the container.
+   *
+   * \param prefix Filename prefix to use for pcap files.
+   * \param n container of nodes.
+   */
+  void EnablePcapCcnx (std::string prefix, NodeContainer n);
+
+  /**
+   * @brief Enable pcap output on the Ccnx and interface pair specified by a 
+   * global node-id (of a previously created node) and interface.  Since there
+   * can be only one Ccnx aggregated to a node, the node-id unambiguously 
+   * determines the Ccnx.
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   * @param nodeid The node identifier/number of the node on which to enable tracing.
+   * @param interface Interface on ccnx on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  void EnablePcapCcnx (std::string prefix, uint32_t nodeid, uint32_t interface, bool explicitFilename);
+
+  /**
+   * @brief Enable pcap output on all Ccnx and interface pairs existing in the 
+   * set of all nodes created in the simulation.
+   *
+   * @param prefix Filename prefix to use for pcap files.
+   */
+  void EnablePcapCcnxAll (std::string prefix);
+
+};
+
+/**
+ * @brief Base class providing common user-level ascii trace operations for 
+ * helpers representing Ccnx protocols .
+ */
+class AsciiTraceHelperForCcnx
+{
+public:
+  /**
+   * @brief Construct an AsciiTraceHelperForCcnx.
+   */
+  AsciiTraceHelperForCcnx () {}
+
+  /**
+   * @brief Destroy an AsciiTraceHelperForCcnx
+   */
+  virtual ~AsciiTraceHelperForCcnx () {}
+
+  /**
+   * @brief Enable ascii trace output on the indicated Ccnx and interface pair.
+   * @internal
+   *
+   * The implementation is expected to use a provided Ptr<OutputStreamWrapper>
+   * if it is non-null.  If the OutputStreamWrapper is null, the implementation
+   * is expected to use a provided prefix to construct a new file name for
+   * each net device using the rules described in the class overview.
+   *
+   * If the prefix is provided, there will be one file per Ccnx and interface pair
+   * created.  In this case, adding a trace context to the file would be pointless,
+   * so the helper implementation is expected to TraceConnectWithoutContext.
+   *
+   * If the output stream object is provided, there may be many different Ccnx 
+   * and interface pairs writing to a single file.  In this case, the trace 
+   * context could be important, so the helper implementation is expected to 
+   * TraceConnect.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param prefix Filename prefix to use for ascii trace files.
+   * @param ccnx Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface The interface on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true.
+   */
+  virtual void EnableAsciiCcnxInternal (Ptr<OutputStreamWrapper> stream, 
+                                        std::string prefix, 
+                                        Ptr<Ccnx> ccnx, 
+                                        uint32_t interface,
+                                        bool explicitFilename) = 0;
+
+  /**
+   * @brief Enable ascii trace output on the indicated ccnx and interface pair.
+   *
+   * @param prefix Filename prefix to use for ascii files.
+   * @param ccnx Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface The interface on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true.
+   */
+  void EnableAsciiCcnx (std::string prefix, Ptr<Ccnx> ccnx, uint32_t interface, bool explicitFilename = false);
+
+  /**
+   * @brief Enable ascii trace output on the indicated Ccnx and interface pair.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param ccnx Ptr<Ccnx> on which you want to enable tracing.
+   * @param interface The interface on which you want to enable tracing.
+   */
+  void EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, Ptr<Ccnx> ccnx, uint32_t interface);
+
+  /**
+   * @brief Enable ascii trace output the indicated ccnx and interface pair
+   * using an ccnx previously named using the ns-3 object name service.
+   *
+   * @param prefix filename prefix to use for ascii files.
+   * @param ccnxName The name of the ccnx on which you want to enable tracing.
+   * @param interface The interface on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true.
+   */
+  void EnableAsciiCcnx (std::string prefix, std::string ccnxName, uint32_t interface, bool explicitFilename = false);
+
+  /**
+   * @brief Enable ascii trace output the indicated net device using a device 
+   * previously named using the ns-3 object name service.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param ccnxName The name of the ccnx on which you want to enable tracing.
+   * @param interface The interface on which you want to enable tracing.
+   */
+  void EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, std::string ccnxName, uint32_t interface);
+
+  /**
+   * @brief Enable ascii trace output on each Ccnx and interface pair in the 
+   * container
+   *
+   * @param prefix Filename prefix to use for ascii files.
+   * @param c CcnxFaceContainer of Ccnx and interface pairs on which to 
+   *          enable tracing.
+   */
+  void EnableAsciiCcnx (std::string prefix, CcnxFaceContainer c);
+
+  /**
+   * @brief Enable ascii trace output on each device in the container which is
+   * of the appropriate type.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param c ccnxInterfaceContainer of ccnx and interface pairs on which to 
+   *          enable tracing.
+   */
+  void EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, CcnxFaceContainer c);
+
+  /**
+   * @brief Enable ascii trace output on all ccnx and interface pairs existing
+   * in the nodes provided in the container.
+   *
+   * \param prefix Filename prefix to use for ascii files.
+   * \param n container of nodes.
+   */
+  void EnableAsciiCcnx (std::string prefix, NodeContainer n);
+
+  /**
+   * @brief Enable ascii trace output on all ccnx and interface pairs existing
+   * in the nodes provided in the container.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * \param n container of nodes.
+   */
+  void EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, NodeContainer n);
+
+  /**
+   * @brief Enable ascii trace output on all Ccnx and interface pairs existing
+   * in the set of all nodes created in the simulation.
+   *
+   * @param prefix Filename prefix to use for ascii files.
+   */
+  void EnableAsciiCcnxAll (std::string prefix);
+
+  /**
+   * @brief Enable ascii trace output on each device (which is of the
+   * appropriate type) in the set of all nodes created in the simulation.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   */
+  void EnableAsciiCcnxAll (Ptr<OutputStreamWrapper> stream);
+
+  /**
+   * @brief Enable pcap output on the Ccnx and interface pair specified by a 
+   * global node-id (of a previously created node) and interface.  Since there
+   * can be only one Ccnx aggregated to a node, the node-id unambiguously 
+   * determines the Ccnx.
+   *
+   * @param prefix Filename prefix to use when creating ascii trace files
+   * @param nodeid The node identifier/number of the node on which to enable
+   *               ascii tracing
+   * @param deviceid The device identifier/index of the device on which to enable
+   *                 ascii tracing
+   * @param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  void EnableAsciiCcnx (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool explicitFilename);
+
+  /**
+   * @brief Enable pcap output on the ccnx and interface pair specified by a 
+   * global node-id (of a previously created node) and interface.  Since there
+   * can be only one ccnx aggregated to a node, the node-id unambiguously 
+   * determines the ccnx.
+   *
+   * @param stream An OutputStreamWrapper representing an existing file to use
+   *               when writing trace data.
+   * @param nodeid The node identifier/number of the node on which to enable
+   *               ascii tracing
+   * @param interface The interface on which you want to enable tracing.
+   * @param explicitFilename Treat the prefix as an explicit filename if true
+   */
+  void EnableAsciiCcnx (Ptr<OutputStreamWrapper> stream, uint32_t nodeid, uint32_t interface, bool explicitFilename);
+
+private:
+  /**
+   * @internal Avoid code duplication.
+   */
+  void EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, 
+                            std::string prefix, 
+                            uint32_t nodeid, 
+                            uint32_t interface,
+                            bool explicitFilename);
+
+  /**
+   * @internal Avoid code duplication.
+   */
+  void EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, NodeContainer n);
+
+  /**
+   * @internal Avoid code duplication.
+   */
+  void EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, std::string prefix, CcnxFaceContainer c);
+
+  /**
+   * @internal Avoid code duplication.
+   */
+  void EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, 
+                            std::string prefix, 
+                            std::string ccnxName, 
+                            uint32_t interface,
+                            bool explicitFilename);
+
+  /**
+   * @internal Avoid code duplication.
+   */
+  void EnableAsciiCcnxImpl (Ptr<OutputStreamWrapper> stream, 
+                            std::string prefix, 
+                            Ptr<Ccnx> ccnx, 
+                            uint32_t interface,
+                            bool explicitFilename);
+};
+
+} // namespace ns3
+
+#endif /* CCNX_TRACE_HELPER_H */
diff --git a/helper/ndn_stupidinterestgenerator_helper.cc b/helper/ndn_stupidinterestgenerator_helper.cc
index 982f283..1699f40 100644
--- a/helper/ndn_stupidinterestgenerator_helper.cc
+++ b/helper/ndn_stupidinterestgenerator_helper.cc
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; c-set-offset 'innamespace 0; -*- */
 //
 //  ndn_stupidinterestgenerator_helper.cpp
 //  Abstraction
@@ -15,51 +16,51 @@
 
 namespace ns3 {
     
-    StupidInterestGeneratorHelper::StupidInterestGeneratorHelper (std::string protocol, Address address)
-    {
-        m_factory.SetTypeId ("ns3::StupidInterestGenerator");
-        m_factory.Set ("Protocol", StringValue (protocol));
-        m_factory.Set ("Remote", AddressValue (address));
-    }
+StupidInterestGeneratorHelper::StupidInterestGeneratorHelper (std::string protocol, Address address)
+{
+	m_factory.SetTypeId ("ns3::StupidInterestGenerator");
+	m_factory.Set ("Protocol", StringValue (protocol));
+	m_factory.Set ("Remote", AddressValue (address));
+}
     
-    void 
-    StupidInterestGeneratorHelper::SetAttribute (std::string name, const AttributeValue &value)
-    {
-        m_factory.Set (name, value);
-    }
+void 
+StupidInterestGeneratorHelper::SetAttribute (std::string name, const AttributeValue &value)
+{
+	m_factory.Set (name, value);
+}
     
-    ApplicationContainer
-    StupidInterestGeneratorHelper::Install (Ptr<Node> node) const
-    {
-        return ApplicationContainer (InstallPriv (node));
-    }
+ApplicationContainer
+StupidInterestGeneratorHelper::Install (Ptr<Node> node) const
+{
+	return ApplicationContainer (InstallPriv (node));
+}
     
-    ApplicationContainer
-    StupidInterestGeneratorHelper::Install (std::string nodeName) const
-    {
-        Ptr<Node> node = Names::Find<Node> (nodeName);
-        return ApplicationContainer (InstallPriv (node));
-    }
+ApplicationContainer
+StupidInterestGeneratorHelper::Install (std::string nodeName) const
+{
+	Ptr<Node> node = Names::Find<Node> (nodeName);
+	return ApplicationContainer (InstallPriv (node));
+}
     
-    ApplicationContainer
-    StupidInterestGeneratorHelper::Install (NodeContainer c) const
-    {
-        ApplicationContainer apps;
-        for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
-        {
-            apps.Add (InstallPriv (*i));
-        }
+ApplicationContainer
+StupidInterestGeneratorHelper::Install (NodeContainer c) const
+{
+	ApplicationContainer apps;
+	for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
+	{
+		apps.Add (InstallPriv (*i));
+	}
         
-        return apps;
-    }
+	return apps;
+}
     
-    Ptr<Application>
-    StupidInterestGeneratorHelper::InstallPriv (Ptr<Node> node) const
-    {
-        Ptr<Application> app = m_factory.Create<Application> ();
-        node->AddApplication (app);
+Ptr<Application>
+StupidInterestGeneratorHelper::InstallPriv (Ptr<Node> node) const
+{
+	Ptr<Application> app = m_factory.Create<Application> ();
+	node->AddApplication (app);
         
-        return app;
-    }
+	return app;
+}
     
 } // namespace ns3
diff --git a/helper/ndn_stupidinterestgenerator_helper.h b/helper/ndn_stupidinterestgenerator_helper.h
index 4f9f6bb..b8a39ca 100644
--- a/helper/ndn_stupidinterestgenerator_helper.h
+++ b/helper/ndn_stupidinterestgenerator_helper.h
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; c-set-offset 'innamespace 0; -*- */
 //
 //  ndn_stupidinterestgenerator_helper.h
 //  Abstraction
diff --git a/helper/ndnabstraction-helper.cc b/helper/ndnabstraction-helper.cc
index e02c5eb..d8d5db3 100644
--- a/helper/ndnabstraction-helper.cc
+++ b/helper/ndnabstraction-helper.cc
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; c-set-offset 'innamespace 0; -*- */
 /*
  *  ndnabstraction-helper.c
  *  XcodeProject
diff --git a/helper/ndnabstraction-helper.h b/helper/ndnabstraction-helper.h
index 52ec0bf..22e64c7 100644
--- a/helper/ndnabstraction-helper.h
+++ b/helper/ndnabstraction-helper.h
@@ -1,3 +1,4 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  *  ndnabstraction-helper.h
  *  XcodeProject
@@ -7,3 +8,6 @@
  *
  */
 
+namespace ns3 {
+
+}
diff --git a/model/ccnx-content-object-header.cc b/model/ccnx-content-object-header.cc
new file mode 100644
index 0000000..726415e
--- /dev/null
+++ b/model/ccnx-content-object-header.cc
@@ -0,0 +1,90 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnx-content-object-header.h"
+
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxContentObjectHeader");
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxContentObjectHeader);
+
+TypeId
+CcnxContentObjectHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxContentObjectHeader")
+    .SetParent<Header> ()
+    .AddConstructor<CcnxContentObjectHeader> ()
+    ;
+  return tid;
+}
+
+CcnxContentObjectHeader::CcnxContentObjectHeader ()
+{
+}
+
+void
+CcnxContentObjectHeader::SetName (const Ptr<Name::Components> &name)
+{
+  m_name = name;
+}
+
+const Name::Components&
+CcnxContentObjectHeader::GetName () const
+{
+  return *m_name;
+}
+
+uint32_t
+CcnxContentObjectHeader::GetSerializedSize (void) const
+{
+  return 0;
+}
+    
+void
+CcnxContentObjectHeader::Serialize (Buffer::Iterator start) const
+{
+  return;
+}
+
+uint32_t
+CcnxContentObjectHeader::Deserialize (Buffer::Iterator start)
+{
+  return 0;
+}
+  
+TypeId
+CcnxContentObjectHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+  
+void
+CcnxContentObjectHeader::Print (std::ostream &os) const
+{
+  os << "ContentObject: " << *m_name;
+}
+
+} // namespace ns3
+
diff --git a/model/content-object-header.h b/model/ccnx-content-object-header.h
similarity index 88%
rename from model/content-object-header.h
rename to model/ccnx-content-object-header.h
index ff2ae26..0800885 100644
--- a/model/content-object-header.h
+++ b/model/ccnx-content-object-header.h
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2011 University of California, Los Angeles
  *
@@ -19,8 +19,8 @@
  *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
-#ifndef _CONTENT_OBJECT_HEADER_H_
-#define _CONTENT_OBJECT_HEADER_H_
+#ifndef _CCNX_CONTENT_OBJECT_HEADER_H_
+#define _CCNX_CONTENT_OBJECT_HEADER_H_
 
 #include "ns3/integer.h"
 #include "ns3/header.h"
@@ -33,8 +33,6 @@
 
 namespace ns3
 {
-namespace NDNabstraction
-{
 
 /**
  * CCNx XML definition of ContentObject
@@ -47,7 +45,7 @@
  *  Simplifications:
  */
   
-class ContentObjectHeader : public Header
+class CcnxContentObjectHeader : public Header
 {
 public:
   /**
@@ -55,7 +53,7 @@
    *
    * Creates a null header
    **/
-  ContentObjectHeader ();
+  CcnxContentObjectHeader ();
 
   /**
    * \brief Set interest name
@@ -102,7 +100,6 @@
   // ? content
 };
 
-} // namespace NDNabstraction
 } // namespace ns3
 
-#endif // _CONTENT_OBJECT_HEADER_H_
+#endif // _CCNX_CONTENT_OBJECT_HEADER_H_
diff --git a/model/ccnx-face.cc b/model/ccnx-face.cc
new file mode 100644
index 0000000..7635a3e
--- /dev/null
+++ b/model/ccnx-face.cc
@@ -0,0 +1,164 @@
+/* -*- 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-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");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxFace);
+
+TypeId 
+CcnxFace::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxFace")
+    .SetParent<Object> ()
+  ;
+  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.
+ */
+CcnxFace::CcnxFace () 
+  : m_ifup (false)
+  , m_metric (1)
+  , m_node (0)
+  , m_device (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+CcnxFace::~CcnxFace ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+CcnxFace::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  m_device = 0;
+  Object::DoDispose ();
+}
+
+void 
+CcnxFace::SetNode (Ptr<Node> node)
+{
+  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)
+{
+  NS_LOG_FUNCTION (metric);
+  m_metric = metric;
+}
+
+uint16_t
+CcnxFace::GetMetric (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_metric;
+}
+
+/**
+ * These are face states and may be distinct from 
+ * NetDevice states, such as found in real implementations
+ * (where the device may be down but face state is still up).
+ */
+bool 
+CcnxFace::IsUp (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_ifup;
+}
+
+bool 
+CcnxFace::IsDown (void) const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return !m_ifup;
+}
+
+void 
+CcnxFace::SetUp (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_ifup = true;
+}
+
+void 
+CcnxFace::SetDown (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_ifup = false;
+}
+
+void
+CcnxFace::Send (Ptr<Packet> packet)
+{
+  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::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-face.h b/model/ccnx-face.h
new file mode 100644
index 0000000..2b5ba5f
--- /dev/null
+++ b/model/ccnx-face.h
@@ -0,0 +1,124 @@
+/* -*- 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_FACE_H
+#define CCNX_FACE_H
+
+#include <list>
+#include <ostream>
+
+#include "ns3/ptr.h"
+#include "ns3/object.h"
+
+namespace ns3 {
+
+class NetDevice;
+class Packet;
+class Node;
+
+/**
+ * \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 face.
+ *
+ * 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 CcnxFace  : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+
+  CcnxFace ();
+  virtual ~CcnxFace();
+
+  virtual void SetNode (Ptr<Node> node); 
+  virtual void SetDevice (Ptr<NetDevice> device);
+
+  /**
+   * \returns the underlying NetDevice. This method cannot return zero.
+   */
+  virtual Ptr<NetDevice> GetDevice (void) const;
+
+  /**
+   * \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. 
+   */
+  virtual void SetMetric (uint16_t metric);
+
+  /**
+   * \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. 
+   */
+  virtual uint16_t GetMetric (void) const;
+
+  /**
+   * 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 face state is still up).
+   */
+  /**
+   * \returns true if this face is enabled, false otherwise.
+   */
+  virtual bool IsUp (void) const;
+
+  /**
+   * \returns true if this face is disabled, false otherwise.
+   */
+  virtual bool IsDown (void) const;
+
+  /**
+   * Enable this face
+   */
+  virtual void SetUp (void);
+
+  /**
+   * Disable this face
+   */
+  virtual void SetDown (void);
+
+  /**
+   * \param p packet to send
+   */ 
+  virtual void Send (Ptr<Packet> p);
+
+protected:
+  virtual void DoDispose (void);
+
+private:
+  bool m_ifup;
+  uint16_t m_metric;
+  Ptr<Node> m_node;
+  Ptr<NetDevice> m_device;
+};
+
+std::ostream& operator<< (std::ostream& os, CcnxFace const& face);
+
+} // namespace ns3
+
+#endif //CCNX_FACE_H
diff --git a/model/ccnx-forwarding-protocol.cc b/model/ccnx-forwarding-protocol.cc
new file mode 100644
index 0000000..afc7f33
--- /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..072c7f9
--- /dev/null
+++ b/model/ccnx-forwarding-protocol.h
@@ -0,0 +1,146 @@
+/* -*- 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 "ns3/output-stream-wrapper.h"
+
+#include "ccnx.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<Packet>, Ptr<CcnxRoute> > SendCallback;
+  typedef Callback<void, Ptr<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<Packet> p, Ptr<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;
+
+
+  // Should be modified to notify about new prefixes ?
+  
+  /**
+   * \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-interest-header.cc b/model/ccnx-interest-header.cc
new file mode 100644
index 0000000..6b322e2
--- /dev/null
+++ b/model/ccnx-interest-header.cc
@@ -0,0 +1,197 @@
+/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+///< #CCN_PR_SCOPE0 (0x20) local scope,
+///< #CCN_PR_SCOPE1 (0x40) this host,
+///< #CCN_PR_SCOPE2 (0x80) immediate neighborhood
+
+#include "ccnx-interest-header.h"
+
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxInterestHeader");
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxInterestHeader);
+
+TypeId
+CcnxInterestHeader::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxInterestHeader")
+    .SetParent<Header> ()
+    .AddConstructor<CcnxInterestHeader> ()
+    ;
+  return tid;
+}
+  
+
+CcnxInterestHeader::CcnxInterestHeader ()
+  : m_minSuffixComponents (-1)
+  , m_maxSuffixComponents (-1)
+  , m_childSelector (false)
+  , m_answerOriginKind (false)
+  , m_scope (-1)
+  , m_interestLifetime (-1)
+  , m_nonce (0)
+{
+}
+
+void
+CcnxInterestHeader::SetName (const Ptr<Name::Components> &name)
+{
+  m_name = name;
+}
+
+const Name::Components&
+CcnxInterestHeader::GetName () const
+{
+  return *m_name;
+}
+
+void
+CcnxInterestHeader::SetMinSuffixComponents (int32_t value)
+{
+  m_minSuffixComponents = value;
+}
+
+int32_t
+CcnxInterestHeader::GetMinSuffixComponents () const
+{
+  return m_minSuffixComponents;
+}
+
+void
+CcnxInterestHeader::SetMaxSuffixComponents (int32_t value)
+{
+  m_maxSuffixComponents = value;
+}
+
+int32_t
+CcnxInterestHeader::GetMaxSuffixComponents () const
+{
+  return m_maxSuffixComponents;
+}
+
+void
+CcnxInterestHeader::SetExclude (const Ptr<Name::Components> &exclude)
+{
+  m_exclude = exclude;
+}
+
+const Name::Components&
+CcnxInterestHeader::GetExclude () const
+{
+  return *m_exclude;
+}
+
+void
+CcnxInterestHeader::EnableChildSelector ()
+{
+  m_childSelector = true;
+}
+
+bool
+CcnxInterestHeader::IsEnabledChildSelector () const
+{
+  return m_childSelector;
+}
+
+void
+CcnxInterestHeader::EnableAnswerOriginKind ()
+{
+  m_answerOriginKind = true;
+}
+
+bool
+CcnxInterestHeader::IsEnabledAnswerOriginKind () const
+{
+  return m_answerOriginKind;
+}
+
+void
+CcnxInterestHeader::SetScope (int8_t scope)
+{
+  m_scope = scope;
+}
+
+int8_t
+CcnxInterestHeader::GetScope () const
+{
+  return m_scope;
+}
+
+void
+CcnxInterestHeader::SetInterestLifetime (intmax_t lifetime)
+{
+  m_interestLifetime = lifetime;
+}
+
+intmax_t
+CcnxInterestHeader::GetInterestLifetime () const
+{
+  return m_interestLifetime;
+}
+
+void
+CcnxInterestHeader::SetNonce (uint32_t nonce)
+{
+  m_nonce = nonce;
+}
+
+uint32_t
+CcnxInterestHeader::GetNonce () const
+{
+  return m_nonce;
+}
+  
+uint32_t
+CcnxInterestHeader::GetSerializedSize (void) const
+{
+  return 0;
+}
+    
+void
+CcnxInterestHeader::Serialize (Buffer::Iterator start) const
+{
+  return;
+}
+
+uint32_t
+CcnxInterestHeader::Deserialize (Buffer::Iterator start)
+{
+  return 0;
+}
+
+TypeId
+CcnxInterestHeader::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+  
+void
+CcnxInterestHeader::Print (std::ostream &os) const
+{
+  os << "Interest: " << *m_name;
+}
+
+}
diff --git a/model/interest-header.h b/model/ccnx-interest-header.h
similarity index 97%
rename from model/interest-header.h
rename to model/ccnx-interest-header.h
index 9d9ba4a..259e156 100644
--- a/model/interest-header.h
+++ b/model/ccnx-interest-header.h
@@ -19,8 +19,8 @@
  *         Alexander Afanasyev <alexander.afanasyev@ucla.edu>
  */
 
-#ifndef _INTEREST_HEADER_H_
-#define _INTEREST_HEADER_H_
+#ifndef _CCNX_INTEREST_HEADER_H_
+#define _CCNX_INTEREST_HEADER_H_
 
 #include "ns3/integer.h"
 #include "ns3/header.h"
@@ -33,8 +33,6 @@
 
 namespace ns3
 {
-namespace NDNabstraction
-{
   
 /**
  * CCNx XML definition of Interest
@@ -126,7 +124,7 @@
    - InterestLifetime: not used if negative
    - Nonce: 32 bit random integer.  If value is 0, will not be serialized
  */
-class InterestHeader : public Header
+class CcnxInterestHeader : public Header
 {
 public:
   /**
@@ -134,7 +132,7 @@
    *
    * Creates a null header
    **/
-  InterestHeader ();
+  CcnxInterestHeader ();
 
   /**
    * \brief Set interest name
@@ -221,7 +219,6 @@
   uint32_t m_nonce; ///< Nonce. not used if zero
 };
 
-} // namespace NDNabstraction
 } // namespace ns3
 
-#endif // _INTEREST_HEADER_H_
+#endif // _CCNX_INTEREST_HEADER_H_
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
new file mode 100644
index 0000000..b906a4c
--- /dev/null
+++ b/model/ccnx-l3-protocol.cc
@@ -0,0 +1,316 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: 
+//
+
+#include "ccnx-l3-protocol.h"
+
+#include "ns3/packet.h"
+#include "ns3/net-device.h"
+#include "ns3/node.h"
+#include "ns3/log.h"
+#include "ns3/callback.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/object-vector.h"
+#include "ns3/boolean.h"
+
+#include "ccnx-face.h"
+#include "ccnx-route.h"
+#include "ccnx-forwarding-protocol.h"
+
+NS_LOG_COMPONENT_DEFINE ("CcnxL3Protocol");
+
+namespace ns3 {
+
+const uint16_t CcnxL3Protocol::PROT_NUMBER = 0x7777;
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxL3Protocol);
+
+TypeId 
+CcnxL3Protocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxL3Protocol")
+    .SetParent<Ccnx> ()
+    .AddConstructor<CcnxL3Protocol> ()
+    .AddTraceSource ("Tx", "Send ccnx packet to outgoing interface.",
+                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_txTrace))
+    .AddTraceSource ("Rx", "Receive ccnx packet from incoming interface.",
+                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_rxTrace))
+    .AddTraceSource ("Drop", "Drop ccnx packet",
+                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_dropTrace))
+    .AddAttribute ("InterfaceList", "The set of Ccnx interfaces associated to this Ccnx stack.",
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&CcnxL3Protocol::m_faces),
+                   MakeObjectVectorChecker<CcnxFace> ())
+
+    .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
+                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_sendOutgoingTrace))
+
+  ;
+  return tid;
+}
+
+CcnxL3Protocol::CcnxL3Protocol()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+CcnxL3Protocol::~CcnxL3Protocol ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+void
+CcnxL3Protocol::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+/*
+ * This method is called by AddAgregate and completes the aggregation
+ * by setting the node in the ccnx stack
+ */
+void
+CcnxL3Protocol::NotifyNewAggregate ()
+{
+  if (m_node == 0)
+    {
+      Ptr<Node>node = this->GetObject<Node>();
+      // verify that it's a valid node and that
+      // the node has not been set before
+      if (node != 0)
+        {
+          this->SetNode (node);
+        }
+    }
+  Object::NotifyNewAggregate ();
+}
+
+void
+CcnxL3Protocol::SetForwardingProtocol (Ptr<CcnxForwardingProtocol> forwardingProtocol)
+{
+  NS_LOG_FUNCTION (this);
+  m_forwardingProtocol = forwardingProtocol;
+  m_forwardingProtocol->SetCcnx (this);
+}
+
+Ptr<CcnxForwardingProtocol>
+CcnxL3Protocol::GetForwardingProtocol (void) const
+{
+  return m_forwardingProtocol;
+}
+
+void 
+CcnxL3Protocol::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+
+  for (CcnxFaceList::iterator i = m_faces.begin (); i != m_faces.end (); ++i)
+    {
+      *i = 0;
+    }
+  m_faces.clear ();
+  m_node = 0;
+  // m_forwardingProtocol = 0;
+  Object::DoDispose ();
+}
+
+uint32_t 
+CcnxL3Protocol::AddFace (Ptr<CcnxFace> face)
+{
+  NS_LOG_FUNCTION (this << *face);
+
+  // Ptr<Node> node = GetObject<Node> (); ///< \todo not sure why this thing should be called...
+  face->SetNode (m_node);
+
+  if (face->GetDevice() != 0)
+    {
+      m_node->RegisterProtocolHandler (MakeCallback (&CcnxL3Protocol::ReceiveFromLower, this), 
+                                       CcnxL3Protocol::PROT_NUMBER, face->GetDevice(), true/*promiscuous mode*/);
+    }
+
+  uint32_t index = m_faces.size ();
+  m_faces.push_back (face);
+  return index;
+}
+
+
+Ptr<CcnxFace>
+CcnxL3Protocol::GetFace (uint32_t index) const
+{
+  if (index < m_faces.size ())
+    {
+      return m_faces[index];
+    }
+  return 0;
+}
+
+uint32_t 
+CcnxL3Protocol::GetNFaces (void) const
+{
+  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)
+{
+  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);
+
+  Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
+  ReceiveAndProcess (ccnxFace, packet);
+}
+
+// Callback from higher level
+void CcnxL3Protocol::ReceiveAndProcess (Ptr<CcnxFace> incomingFace, Ptr<Packet> packet)
+{
+  if ( incomingFace->IsUp ())
+    {
+      NS_LOG_LOGIC ("Dropping received packet -- interface is down");
+      m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), incomingFace);
+      return;
+    }
+  
+  m_rxTrace (packet, m_node->GetObject<Ccnx> (), incomingFace);
+
+  NS_ASSERT_MSG (m_forwardingProtocol != 0, "Need a forwarding protocol object to process packets");
+  if (!m_forwardingProtocol->RouteInput (packet, incomingFace,
+                                      MakeCallback (&CcnxL3Protocol::Send, this),
+                                      MakeCallback (&CcnxL3Protocol::RouteInputError, this)
+                                      ))
+    {
+      NS_LOG_WARN ("No route found for forwarding packet.  Drop.");
+      m_dropTrace (packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), incomingFace);
+    }
+}
+
+
+void
+CcnxL3Protocol::Send (Ptr<Packet> packet, Ptr<CcnxRoute> route)
+{
+  NS_LOG_FUNCTION (this << "packet: " << packet << ", route: "<< route);
+  
+  if (route == 0)
+    {
+      NS_LOG_WARN ("No route to host.  Drop.");
+      m_dropTrace (packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), 0);
+      return;
+    }
+  Ptr<CcnxFace> outFace = route->GetOutputFace ();
+
+  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);
+    }
+}
+
+
+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_forwardingProtocol != 0)
+    {
+      m_forwardingProtocol->NotifyInterfaceUp (i);
+    }
+}
+
+void 
+CcnxL3Protocol::SetDown (uint32_t ifaceIndex)
+{
+  NS_LOG_FUNCTION (this << ifaceIndex);
+  Ptr<CcnxFace> interface = GetFace (ifaceIndex);
+  interface->SetDown ();
+
+  if (m_forwardingProtocol != 0)
+    {
+      m_forwardingProtocol->NotifyInterfaceDown (ifaceIndex);
+    }
+}
+
+void
+CcnxL3Protocol::RouteInputError (Ptr<Packet> p)//, Socket::SocketErrno sockErrno)
+{
+  // NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
+  // NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno); 
+  m_dropTrace (p, DROP_ROUTE_ERROR, m_node->GetObject<Ccnx> (), 0);
+}
+
+} //namespace ns3
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
new file mode 100644
index 0000000..3af0c9a
--- /dev/null
+++ b/model/ccnx-l3-protocol.h
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+//
+// Copyright (c) 2006 Georgia Tech Research Corporation
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation;
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//
+// Author: 
+//
+
+#ifndef CCNX_L3_PROTOCOL_H
+#define CCNX_L3_PROTOCOL_H
+
+#include <list>
+#include <vector>
+#include <stdint.h>
+#include "ns3/ptr.h"
+#include "ns3/net-device.h"
+#include "ns3/traced-callback.h"
+
+#include "ccnx.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Node;
+class CcnxFace;
+class CcnxRoute;
+class CcnxForwardingProtocol;
+
+/**
+ * \brief Implement the Ccnx layer.
+ * 
+ * This is the actual implementation of IP.  It contains APIs to send and
+ * receive packets at the IP layer, as well as APIs for IP routing.
+ *
+ * This class contains two distinct groups of trace sources.  The
+ * trace sources 'Rx' and 'Tx' are called, respectively, immediately
+ * after receiving from the NetDevice and immediately before sending
+ * to a NetDevice for transmitting a packet.  These are low level
+ * trace sources that include the CcnxHeader already serialized into
+ * the packet.  In contrast, the Drop, SendOutgoing, UnicastForward,
+ * and LocalDeliver trace sources are slightly higher-level and pass
+ * around the CcnxHeader as an explicit parameter and not as part of
+ * the packet.
+ */
+class CcnxL3Protocol : public Ccnx
+{
+public:
+  static TypeId GetTypeId (void);
+  static const uint16_t PROT_NUMBER;
+
+  CcnxL3Protocol();
+  virtual ~CcnxL3Protocol ();
+
+  /**
+   * \enum DropReason
+   * \brief Reason why a packet has been dropped.
+   */
+  enum DropReason 
+  {
+    /** \todo  Fill reasons from QualNet code */
+    DROP_DUPLICATE_INTEREST=1,  /**< Duplicate Interest */
+    DROP_CONGESTION, /**< Congestion detected */
+    DROP_NO_ROUTE,   /**< No route to host */
+    DROP_INTERFACE_DOWN,   /**< Interface is down so can not send packet */
+    DROP_ROUTE_ERROR,   /**< Route error */
+  };
+
+  void SetNode (Ptr<Node> node);
+
+  // functions defined in base class Ccnx
+  
+  void SetForwardingProtocol (Ptr<CcnxForwardingProtocol> forwardingProtocol);
+  Ptr<CcnxForwardingProtocol> GetForwardingProtocol (void) const;
+
+  /**
+   * Lower layer calls this method after calling L3Demux::Lookup
+   *
+   * \param device network device
+   * \param p the packet
+   * \param protocol lower layer protocol value
+   * \param from lower layer address of the correspondant
+   * \param to lower layer address of the destination
+   * \param packetType type of the packet (broadcast/multicast/unicast/otherhost)
+   */
+  void ReceiveFromLower (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 ReceiveAndProcess (Ptr<CcnxFace> face, Ptr<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.
+   */
+  virtual void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route);
+
+  virtual uint32_t AddFace (Ptr<CcnxFace> face);
+  virtual uint32_t GetNFaces (void) 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:
+  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 &);
+
+  /**
+   * Helper function to get CcnxFace from NetDevice
+   */
+  Ptr<CcnxFace> GetFaceForDevice (Ptr<const NetDevice> device) const;
+  
+  void RouteInputError (Ptr<Packet> p);
+                        //, Socket::SocketErrno sockErrno);
+
+private:
+  typedef std::vector<Ptr<CcnxFace> > CcnxFaceList;
+  CcnxFaceList m_faces;
+
+  Ptr<Node> m_node;
+  Ptr<CcnxForwardingProtocol> m_forwardingProtocol;
+
+  TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_sendOutgoingTrace;
+  TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_unicastForwardTrace;
+  TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_localDeliverTrace;
+
+  // The following two traces pass a packet with an IP header
+  TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_txTrace;
+  TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_rxTrace;
+  // <ip-header, payload, reason, ifindex> (ifindex not valid if reason is DROP_NO_ROUTE)
+  TracedCallback<Ptr<const Packet>, DropReason, Ptr<const Ccnx>, Ptr<const CcnxFace> > m_dropTrace;
+};
+  
+} // Namespace ns3
+
+#endif /* CCNX_L3_PROTOCOL_H */
diff --git a/model/ccnx-local-face.cc b/model/ccnx-local-face.cc
new file mode 100644
index 0000000..d5de90f
--- /dev/null
+++ b/model/ccnx-local-face.cc
@@ -0,0 +1,101 @@
+/* -*- 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-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)
+{
+  NS_ASSERT_MSG (false, "It is impossible to set device to LocalFace");
+}
+
+Ptr<NetDevice>
+CcnxLocalFace::GetDevice (void) const
+{
+  return 0;
+}
+
+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..63ea570
--- /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
new file mode 100644
index 0000000..987c001
--- /dev/null
+++ b/model/ccnx-route.cc
@@ -0,0 +1,61 @@
+/* -*- 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 "ccnx-route.h"
+
+#include "ns3/ccnx-face.h"
+#include "ns3/assert.h"
+
+namespace ns3 {
+
+CcnxRoute::CcnxRoute ()
+{
+}
+
+void
+CcnxRoute::SetPrefix (const Ptr<Name::Components> &prefix)
+{
+  m_prefix = prefix;
+}
+
+const Name::Components&
+CcnxRoute::GetPrefix (void) const
+{
+  return *m_prefix;
+}
+
+void
+CcnxRoute::SetOutputFace (Ptr<CcnxFace> outputFace)
+{
+  m_outputFace = outputFace;
+}
+
+Ptr<CcnxFace>
+CcnxRoute::GetOutputFace (void) const
+{
+  return m_outputFace;
+}
+
+std::ostream& operator<< (std::ostream& os, CcnxRoute const& route)
+{
+  os << "prefix=" << route.GetPrefix () << ", " << route.GetOutputFace ();
+  return os;
+}
+
+} //namespace ns3
diff --git a/model/ccnx-route.h b/model/ccnx-route.h
new file mode 100644
index 0000000..4d45023
--- /dev/null
+++ b/model/ccnx-route.h
@@ -0,0 +1,76 @@
+/* -*- 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_ROUTE_H
+#define CCNX_ROUTE_H
+
+#include <list>
+#include <map>
+#include <ostream>
+
+#include "ns3/ptr.h"
+#include "ns3/simple-ref-count.h"
+#include "ns3/name-components.h"
+
+namespace ns3 {
+  
+class CcnxFace;
+
+/**
+ * \ingroup ccnxRouting
+ *
+ *\brief Ccnx route cache entry (similar to Linux struct rtable)
+ *
+ * This is a reference counted object.  In the future, we will add other 
+ * entries from struct dst_entry, struct rtable, and struct dst_ops as needed.
+ */
+class CcnxRoute : public SimpleRefCount<CcnxRoute> 
+{
+public:
+  CcnxRoute ();
+
+  /**
+   * \param dest Destination CcnxAddress
+   */
+  void SetPrefix (const Ptr<Name::Components> &dest);
+  /**
+   * \return Destination CcnxAddress of the route
+   */
+  const Name::Components& GetPrefix (void) const;
+
+  /**
+   * Equivalent in Linux to dst_entry.dev
+   *
+   * \param outputDevice pointer to NetDevice for outgoing packets
+   */
+  void SetOutputFace (Ptr<CcnxFace> outputDevice);
+  /**
+   * \return pointer to NetDevice for outgoing packets
+   */
+  Ptr<CcnxFace> GetOutputFace (void) const;
+
+private:
+  Ptr<Name::Components> m_prefix;
+  Ptr<CcnxFace> m_outputFace;
+};
+
+std::ostream& operator<< (std::ostream& os, CcnxRoute const& route);
+
+} //namespace ns3
+
+#endif /* CCNX_ROUTE_H */
diff --git a/model/ccnx.cc b/model/ccnx.cc
new file mode 100644
index 0000000..f54d1b0
--- /dev/null
+++ b/model/ccnx.cc
@@ -0,0 +1,48 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 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 "ns3/assert.h" 
+#include "ns3/node.h" 
+#include "ns3/boolean.h"
+
+#include "ccnx.h"
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (Ccnx);
+
+TypeId 
+Ccnx::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ccnx")
+    .SetParent<Object> ()
+  ;
+  return tid;
+}
+
+Ccnx::Ccnx ()
+{
+}
+
+Ccnx::~Ccnx ()
+{
+}
+
+} // namespace ns3
diff --git a/model/ccnx.h b/model/ccnx.h
new file mode 100644
index 0000000..b2cde94
--- /dev/null
+++ b/model/ccnx.h
@@ -0,0 +1,168 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 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: 
+ */
+#ifndef CCNX_H
+#define CCNX_H
+
+#include <stdint.h>
+#include "ns3/object.h"
+#include "ns3/socket.h"
+#include "ns3/callback.h"
+
+#include "ccnx-route.h"
+
+namespace ns3 {
+
+class Node;
+class NetDevice;
+class Packet;
+class CcnxForwardingProtocol;
+
+/**
+ * \ingroup internet
+ * \defgroup ccnx Ccnx
+ */
+/**
+ * \ingroup ccnx
+ * \brief Access to the Ccnx forwarding table, interfaces, and configuration
+ *
+ * This class defines the API to manipulate the following aspects of
+ * the Ccnx implementation:
+ * -# register a NetDevice for use by the Ccnx layer (basically, to
+ * create Ccnx-related state such as addressing and neighbor cache that 
+ * is associated with a NetDevice)
+ * -# manipulate the status of the NetDevice from the Ccnx perspective, 
+ * such as marking it as Up or Down, 
+ // * -# adding, deleting, and getting addresses associated to the Ccnx 
+ // * interfaces.
+ * -# exporting Ccnx configuration attributes
+ * 
+ * Each NetDevice has conceptually a single Ccnx interface associated
+ * with it.
+ */
+class Ccnx : public Object
+{
+public:
+  static TypeId GetTypeId (void);
+  Ccnx ();
+  virtual ~Ccnx ();
+
+  /**
+   * \brief Register a new forwarding protocol to be used by this Ccnx stack
+   *
+   * This call will replace any forwarding protocol that has been previously 
+   * registered.  If you want to add multiple forwarding protocols, you must
+   * add them to a CcnxListForwardingProtocol directly.
+   * 
+   * \param forwardingProtocol smart pointer to CcnxForwardingProtocol object
+   */
+  virtual void SetForwardingProtocol (Ptr<CcnxForwardingProtocol> forwardingProtocol) = 0;
+
+  /**
+   * \brief Get the forwarding protocol to be used by this Ccnx stack
+   * 
+   * \returns smart pointer to CcnxForwardingProtocol object, or null pointer if none
+   */
+  virtual Ptr<CcnxForwardingProtocol> GetForwardingProtocol (void) const = 0;
+
+  /**
+   * \param device device to add to the list of Ccnx interfaces
+   *        which can be used as output interfaces during packet forwarding.
+   * \returns the index of the Ccnx interface added.
+   *
+   * Once a device has been added, it can never be removed: if you want
+   * to disable it, you can invoke Ccnx::SetDown which will
+   * make sure that it is never used during packet forwarding.
+   */
+  virtual uint32_t AddFace (Ptr<CcnxFace> face) = 0;
+
+  /**
+   * \returns the number of interfaces added by the user.
+   */
+  virtual uint32_t GetNFaces (void) const = 0;
+
+  /**
+   * \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.
+   */
+  // virtual void Send (Ptr<Packet> packet, Ptr<CcnxRoute> route) = 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;
+
+  // /**
+  //  * \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 face The face number of an Ccnx face
+   * \param metric forwarding metric (cost) associated to the underlying 
+   *          Ccnx interface
+   */
+  virtual void SetMetric (uint32_t face, uint16_t metric) = 0;
+
+  /**
+   * \param face The interface number of an Ccnx interface
+   * \returns forwarding metric (cost) associated to the underlying 
+   *          Ccnx interface
+   */
+  virtual uint16_t GetMetric (uint32_t face) const = 0;
+
+  /**
+   * \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 face) const = 0;
+
+  /**
+   * \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 face) const = 0;
+
+  /**
+   * \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 face) = 0;
+
+  /**
+   * \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 face) = 0;
+};
+
+} // namespace ns3 
+
+#endif /* CCNX_H */
diff --git a/model/content-object-header.cc b/model/content-object-header.cc
deleted file mode 100644
index 4399afd..0000000
--- a/model/content-object-header.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2011 University of California, Los Angeles
- *
- * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
- */
-
-#include "content-object-header.h"
-
-namespace ns3
-{
-namespace NDNabstraction
-{
-
-  ContentObjectHeader::ContentObjectHeader ()
-  {
-  }
-
-  void
-  ContentObjectHeader::SetName (const Ptr<Name::Components> &name)
-  {
-    m_name = name;
-  }
-
-  const Name::Components&
-  ContentObjectHeader::GetName () const
-  {
-    return *m_name;
-  }
-
-  uint32_t
-  ContentObjectHeader::GetSerializedSize (void) const
-  {
-    return 0;
-  }
-    
-  void
-  ContentObjectHeader::Serialize (Buffer::Iterator start) const
-  {
-    return;
-  }
-
-  uint32_t
-  ContentObjectHeader::Deserialize (Buffer::Iterator start)
-  {
-    return 0;
-  }
-
-  TypeId
-  ContentObjectHeader::GetTypeId (void)
-  {
-    static TypeId tid = TypeId ("ns3::NDNabstraction::ContentObjectHeader")
-      .SetParent<Header> ()
-      .AddConstructor<ContentObjectHeader> ()
-      ;
-    return tid;
-  }
-  
-  TypeId
-  ContentObjectHeader::GetInstanceTypeId (void) const
-  {
-    return GetTypeId ();
-  }
-  
-  void
-  ContentObjectHeader::Print (std::ostream &os) const
-  {
-    os << "ContentObject: " << *m_name;
-  }
-}
-}
diff --git a/model/interest-header.cc b/model/interest-header.cc
deleted file mode 100644
index f9300c4..0000000
--- a/model/interest-header.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
-/*
- * Copyright (c) 2011 University of California, Los Angeles
- *
- * 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: Ilya Moiseenko <iliamo@cs.ucla.edu>
- */
-
-///< #CCN_PR_SCOPE0 (0x20) local scope,
-///< #CCN_PR_SCOPE1 (0x40) this host,
-///< #CCN_PR_SCOPE2 (0x80) immediate neighborhood
-
-#include "interest-header.h"
-
-namespace ns3
-{
-namespace NDNabstraction
-{
-
-  InterestHeader::InterestHeader ()
-    : m_minSuffixComponents (-1)
-    , m_maxSuffixComponents (-1)
-    , m_childSelector (false)
-    , m_answerOriginKind (false)
-    , m_scope (-1)
-    , m_interestLifetime (-1)
-    , m_nonce (0)
-  {
-  }
-
-  void
-  InterestHeader::SetName (const Ptr<Name::Components> &name)
-  {
-    m_name = name;
-  }
-
-  const Name::Components&
-  InterestHeader::GetName () const
-  {
-    return *m_name;
-  }
-
-  void
-  InterestHeader::SetMinSuffixComponents (int32_t value)
-  {
-    m_minSuffixComponents = value;
-  }
-
-  int32_t
-  InterestHeader::GetMinSuffixComponents () const
-  {
-    return m_minSuffixComponents;
-  }
-
-  void
-  InterestHeader::SetMaxSuffixComponents (int32_t value)
-  {
-    m_maxSuffixComponents = value;
-  }
-
-  int32_t
-  InterestHeader::GetMaxSuffixComponents () const
-  {
-    return m_maxSuffixComponents;
-  }
-
-  void
-  InterestHeader::SetExclude (const Ptr<Name::Components> &exclude)
-  {
-    m_exclude = exclude;
-  }
-
-  const Name::Components&
-  InterestHeader::GetExclude () const
-  {
-    return *m_exclude;
-  }
-
-  void
-  InterestHeader::EnableChildSelector ()
-  {
-    m_childSelector = true;
-  }
-
-  bool
-  InterestHeader::IsEnabledChildSelector () const
-  {
-    return m_childSelector;
-  }
-
-  void
-  InterestHeader::EnableAnswerOriginKind ()
-  {
-    m_answerOriginKind = true;
-  }
-
-  bool
-  InterestHeader::IsEnabledAnswerOriginKind () const
-  {
-    return m_answerOriginKind;
-  }
-
-  void
-  InterestHeader::SetScope (int8_t scope)
-  {
-    m_scope = scope;
-  }
-
-  int8_t
-  InterestHeader::GetScope () const
-  {
-    return m_scope;
-  }
-
-  void
-  InterestHeader::SetInterestLifetime (intmax_t lifetime)
-  {
-    m_interestLifetime = lifetime;
-  }
-
-  intmax_t
-  InterestHeader::GetInterestLifetime () const
-  {
-    return m_interestLifetime;
-  }
-
-  void
-  InterestHeader::SetNonce (uint32_t nonce)
-  {
-    m_nonce = nonce;
-  }
-
-  uint32_t
-  InterestHeader::GetNonce () const
-  {
-    return m_nonce;
-  }
-  
-  uint32_t
-  InterestHeader::GetSerializedSize (void) const
-  {
-    return 0;
-  }
-    
-  void
-  InterestHeader::Serialize (Buffer::Iterator start) const
-  {
-    return;
-  }
-
-  uint32_t
-  InterestHeader::Deserialize (Buffer::Iterator start)
-  {
-    return 0;
-  }
-
-  TypeId
-  InterestHeader::GetTypeId (void)
-  {
-    static TypeId tid = TypeId ("ns3::NDNabstraction::InterestHeader")
-      .SetParent<Header> ()
-      .AddConstructor<InterestHeader> ()
-      ;
-    return tid;
-  }
-  
-  TypeId
-  InterestHeader::GetInstanceTypeId (void) const
-  {
-    return GetTypeId ();
-  }
-  
-  void
-  InterestHeader::Print (std::ostream &os) const
-  {
-    os << "Interest: " << *m_name;
-  }
-}
-}
diff --git a/model/name-components.cc b/model/name-components.cc
index a6aae87..c0e9ea0 100644
--- a/model/name-components.cc
+++ b/model/name-components.cc
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2011 University of California, Los Angeles
  *
@@ -28,7 +28,6 @@
 using namespace std;
 
 namespace ns3 {
-namespace NDNabstraction {
 namespace Name {
 
 Components::Components ()
@@ -87,5 +86,4 @@
 
 }
 }
-}
 
diff --git a/model/name-components.h b/model/name-components.h
index 2cdfd99..6faa38c 100644
--- a/model/name-components.h
+++ b/model/name-components.h
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2011 University of California, Los Angeles
  *
@@ -27,7 +27,6 @@
 #include <list>
 
 namespace ns3 {
-namespace NDNabstraction {
 namespace Name {
 
 class Components : public SimpleRefCount<Components>
@@ -60,7 +59,6 @@
 std::ostream & operator << (std::ostream &os, const Components &components);
 
 } // Namespace Name
-} // namespace NDNabstraction 
 } // namespace ns3
 
 #endif // _NDN_NAME_COMPONENTS_H_
diff --git a/model/ndnabstraction-header.cc b/model/ndnabstraction-header.cc
index a7ea402..ccb3cf3 100644
--- a/model/ndnabstraction-header.cc
+++ b/model/ndnabstraction-header.cc
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2011 University of California, Los Angeles
  *
diff --git a/model/ndnabstraction-header.h b/model/ndnabstraction-header.h
index 2cbd4a3..cd172c7 100644
--- a/model/ndnabstraction-header.h
+++ b/model/ndnabstraction-header.h
@@ -1,4 +1,4 @@
-/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /*
  * Copyright (c) 2011 University of California, Los Angeles
  *
diff --git a/wscript b/wscript
index 1670c53..d5ea04d 100644
--- a/wscript
+++ b/wscript
@@ -1,53 +1,36 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
+import os
+import Logs
+import Utils
+
 def build(bld):
-    module = bld.create_ns3_module('NDNabstraction', ['applications', 'core', 'network', 'internet', 'point-to-point'])
-    module.includes = '.'
-    module.source = [
-        'model/ccn/ccn_charbuf.cc',
-        'model/ccn/ccn_name_util.cc',
-        'model/ccn/ccn_coding.cc',
-        'model/ccn/ccn_indexbuf.cc',
-        'model/ccn/ccn_random.cc',
-        'model/ccn/ccn_buf_decoder.cc',
-        'model/ccn/ccn_buf_encoder.cc',
-        
-        'model/name-components.cc',
-        'model/interest-header.cc',
-        'model/content-object-header.cc',
+    module = bld.create_ns3_module ('NDNabstraction', ['applications', 'core', 'network', 'point-to-point'])
+    module.find_sources_in_dirs (['model', 'model/ccn', 'apps', 'helper'],[],['.cc']);
 
-        'apps/stupid-interest-generator.cc',
-        'apps/stupid-interest-sink.cc',
-        ]
-
-    module_test = bld.create_ns3_module_test_library('NDNabstraction')
-    module_test.source = [
-        'test/ndnabstraction-basictest.cc',
-		]
+    tests = bld.create_ns3_module_test_library('NDNabstraction')
+    tests.find_sources_in_dirs( ['test'], [], ['.cc'] );
 
     headers = bld.new_task_gen('ns3header')
     headers.module = 'NDNabstraction'
-    headers.source = [
-        'model/ccn/ccn.h',
-        'model/ccn/ccn_charbuf.h',
-        'model/ccn/ccn_coding.h',
-        'model/ccn/ccn_name_util.h',
-        'model/ccn/ccn_indexbuf.h',
-        'model/ccn/ccn_random.h',
+    headers.find_sources_in_dirs( ['model', 'model/ccn', 'apps', 'helper'], [], ['.h'] );
 
-        # 'model/ndnabstraction-header.h',
-
-        'model/name-components.h',
-        'model/interest-header.h',
-        'model/content-object-header.h',
-
-        # 'helper/ndnabstraction-helper.h',
-        'helper/ndn_stupidinterestgenerator_helper.h',
-
-        'apps/stupid-interest-generator.h',
-        'apps/stupid-interest-sink.h'
-        ]
-
+    for path in ["examples"]:
+        anode = bld.path.find_dir (path)
+        if not anode or not anode.is_child_of(bld.srcnode):
+            raise Utils.WscriptError("Unable to use '%s' - either because \
+            it's not a relative path"", or it's not child of \
+            '%s'."%(name,bld.srcnode))
+        bld.rescan(anode)
+        for filename in bld.cache_dir_contents[anode.id]:
+            if filename.startswith('.') or not filename.endswith(".cc"):
+                continue
+            name = filename[:-len(".cc")]
+            obj = bld.create_ns3_program(name, ['NDNabstraction'])
+            obj.path = obj.path.find_dir (path)
+            obj.source = filename
+            obj.target = name
+            obj.name = obj.target
 
     if bld.env['ENABLE_OPENSSL']:
         module.uselib = 'OPENSSL'
@@ -56,8 +39,4 @@
         bld.add_subdirs('examples')
 
     bld.ns3_python_bindings()
-    #bld.env['CXXFLAGS']=[filter(lambda x: x not in bld.env, sublist) for sublist in [['-Wall'], ['-Werror'], ['-Wextra']]]
-    # bld.env['CXXFLAGS']=[]
-    # bld.env['CFLAGS']=[]
     
-