Merge remote-tracking branch 'git.irl/Ilya'
diff --git a/examples/abilene-topology.cc b/examples/abilene-topology.cc
index 8c83930..02aa54b 100644
--- a/examples/abilene-topology.cc
+++ b/examples/abilene-topology.cc
@@ -72,15 +72,29 @@
 }
 
 
-struct AggregateTrace
+struct AggregateAppTrace
 {
-  AggregateTrace ()
+  AggregateAppTrace ()
     : m_transmittedInterests (0)
     , m_transmittedData (0)
     , m_receivedInterests (0)
     , m_receivedNacks (0)
     , m_receivedData (0)
   {
+    Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/TransmittedInterests",
+                     MakeCallback (&AggregateAppTrace::TransmittedInterests, this));
+
+    Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/ReceivedNacks",
+                     MakeCallback (&AggregateAppTrace::ReceivedNacks, this));
+
+    Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxProducer/ReceivedInterests",
+                     MakeCallback (&AggregateAppTrace::ReceivedInterests, this));
+  
+    Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxProducer/TransmittedContentObjects",
+                     MakeCallback (&AggregateAppTrace::TransmittedData, this));
+
+    Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/ReceivedContentObjects",
+                     MakeCallback (&AggregateAppTrace::ReceivedData, this));
   }
   
   void
@@ -130,7 +144,7 @@
 };
 
 ostream&
-operator << (ostream &os, const AggregateTrace &trace)
+operator << (ostream &os, const AggregateAppTrace &trace)
 {
   os << ">> (i): " << trace.m_transmittedInterests << "\n";
   os << ">> (d): " << trace.m_transmittedData << "\n";
@@ -140,41 +154,99 @@
   return os;
 }
 
-// static void OnTransmittedInterest (std::string context, Ptr<const CcnxInterestHeader> header, 
-//                                    Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
-// {
-//   transmittedInterests++;
-// }
+struct AggregateCcnxTrace
+{
+  AggregateCcnxTrace (const std::string &node = "*")
+    : m_inInterests (0)
+    , m_outInterests (0)
+    , m_dropInterests (0)
+    , m_inNacks (0)
+    , m_outNacks (0)
+    , m_dropNacks (0)
+    , m_inData (0)
+    , m_outData (0)
+    , m_dropData (0)
+  {
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/ForwardingStrategy/OutInterests",
+                     MakeCallback (&AggregateCcnxTrace::OutInterests, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/InInterests",
+                     MakeCallback (&AggregateCcnxTrace::InInterests, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/DropInterests",
+                     MakeCallback (&AggregateCcnxTrace::DropInterests, this));
 
-// static void OnReceivedInterest (std::string context, Ptr<const CcnxInterestHeader> header, 
-//                                 Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
-// {
-//   receivedInterests++;
-// }
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/OutNacks",
+                     MakeCallback (&AggregateCcnxTrace::OutNacks, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/InNacks",
+                     MakeCallback (&AggregateCcnxTrace::InNacks, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/DropNacks",
+                     MakeCallback (&AggregateCcnxTrace::DropNacks, this));
 
-// static void OnDroppedInterest (std::string context, Ptr<const CcnxInterestHeader> header, CcnxL3Protocol::DropReason reason,
-//                                Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
-// {
-//   droppedInterests++;
-// }
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/OutData",
+                     MakeCallback (&AggregateCcnxTrace::OutData, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/InData",
+                     MakeCallback (&AggregateCcnxTrace::InData, this));
+    Config::Connect ("/NodeList/"+node+"/$ns3::CcnxL3Protocol/DropData",
+                     MakeCallback (&AggregateCcnxTrace::DropData, this));
+  }
 
-// static void OnTransmittedData (std::string context, Ptr<const CcnxContentObjectHeader> header, Ptr<const Packet> packet,
-//                                CcnxL3Protocol::ContentObjectSource source, Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
-// {
-//     transmittedData++;    
-// }
+  void OutInterests  (std::string context,
+                      Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace>)
+  { m_outInterests++; }
+  void InInterests   (std::string context,
+                      Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace>)
+  { m_inInterests++; }
+  void DropInterests (std::string context,
+                      Ptr<const CcnxInterestHeader>, Ccnx::DropReason, Ptr<const CcnxFace>)
+  { m_dropInterests++; }
 
-// static void OnReceivedData (std::string context, Ptr<const CcnxContentObjectHeader> header, Ptr<const Packet> packet,
-//                             Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
-// {
-//     receivedData++;
-// }
+  void OutNacks  (std::string context,
+                  Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace>)
+  { m_outNacks++; }
+  void InNacks   (std::string context,
+                  Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace>)
+  { m_inNacks++; }
+  void DropNacks (std::string context,
+                  Ptr<const CcnxInterestHeader>, Ccnx::DropReason, Ptr<const CcnxFace>)
+  { m_dropNacks++; }
 
-// static void OnDroppedData (std::string context, Ptr<const CcnxContentObjectHeader> header, Ptr<const Packet> packet,
-//                            CcnxL3Protocol::DropReason reason, Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face )
-// {
-//     droppedData++;
-// }
+  void OutData  (std::string context,
+                 Ptr<const CcnxContentObjectHeader>, bool fromCache, Ptr<const CcnxFace>)
+  { m_inData++; }
+  void InData   (std::string context,
+                 Ptr<const CcnxContentObjectHeader>, Ptr<const CcnxFace>)
+  { m_outData++; }
+  void DropData (std::string context,
+                 Ptr<const CcnxContentObjectHeader>, Ccnx::DropReason, Ptr<const CcnxFace>)
+  { m_dropData++; }
+
+  uint64_t m_inInterests;
+  uint64_t m_outInterests;
+  uint64_t m_dropInterests;
+  uint64_t m_inNacks;
+  uint64_t m_outNacks;
+  uint64_t m_dropNacks;
+  uint64_t m_inData;
+  uint64_t m_outData;
+  uint64_t m_dropData;
+};
+
+ostream&
+operator << (ostream &os, const AggregateCcnxTrace &trace)
+{
+  os << "(Interests)\n";
+  os << ">> (in):   " << trace.m_inInterests   << "\n";
+  os << ">> (out):  " << trace.m_outInterests  << "\n";
+  os << "<< (drop): " << trace.m_dropInterests << "\n";
+  os << "(Nacks)\n";
+  os << "<< (in):   " << trace.m_inNacks   << "\n";
+  os << "<< (out):  " << trace.m_outNacks  << "\n";
+  os << "<< (drop): " << trace.m_dropNacks << "\n";
+  os << "(Data)\n";
+  os << ">> (in):   " << trace.m_inData   << "\n";
+  os << ">> (out):  " << trace.m_outData  << "\n";
+  os << "<< (drop): " << trace.m_dropData << "\n";
+  return os;
+}
 
 int 
 main (int argc, char *argv[])
@@ -235,8 +307,8 @@
   CcnxConsumerHelper consumerHelper ("/5");
   ApplicationContainer consumers = consumerHelper.Install (Names::Find<Node> ("/abilene", "ATLAng"));
     
-  // CcnxProducerHelper producerHelper ("/5",1024);
-  // ApplicationContainer producers = producerHelper.Install (Names::Find<Node> ("/abilene", "IPLSng"));
+  CcnxProducerHelper producerHelper ("/5",1024);
+  ApplicationContainer producers = producerHelper.Install (Names::Find<Node> ("/abilene", "IPLSng"));
 
   // // Populate FIB based on IPv4 global routing controller
   // ccnxHelper.InstallFakeGlobalRoutes ();
@@ -257,36 +329,9 @@
     }
 
   // NS_LOG_INFO ("Configure Tracing.");
-  AggregateTrace trace;
-  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/TransmittedInterests",
-                   MakeCallback (&AggregateTrace::TransmittedInterests, &trace));
-
-  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/ReceivedNacks",
-                   MakeCallback (&AggregateTrace::ReceivedNacks, &trace));
-
-  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxProducer/ReceivedInterests",
-                   MakeCallback (&AggregateTrace::ReceivedInterests, &trace));
-  
-  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxProducer/TransmittedContentObjects",
-                   MakeCallback (&AggregateTrace::TransmittedData, &trace));
-
-  Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::CcnxConsumer/ReceivedContentObjects",
-                   MakeCallback (&AggregateTrace::ReceivedData, &trace));
-
-  // Config::Connect("/NodeList/*/ns3::CcnxL3Protocol/TransmittedInterestTrace",
-  //                                MakeCallback (&OnTransmittedInterest));
-  // Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/ReceivedInterestTrace",
-  //                    MakeCallback (&OnReceivedInterest));
-  // Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/DroppedInterestTrace",
-  //                    MakeCallback (&OnDroppedInterest));
+  AggregateAppTrace appTrace;
+  AggregateCcnxTrace ccnxTrace ("1");
     
-  // Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/ReceivedDataTrace",
-  //                    MakeCallback (&OnReceivedData));
-  // Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/TransmittedDataTrace",
-  //                    MakeCallback (&OnTransmittedData));
-  // Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/DroppedDataTrace",
-  //                    MakeCallback (&OnDroppedData));
-  
   config.ConfigureAttributes ();  
   
   NS_LOG_INFO ("Run Simulation.");
@@ -294,12 +339,7 @@
   Simulator::Destroy ();
   NS_LOG_INFO ("Done.");
 
-  // NS_LOG_INFO("Total received interests = " << receivedInterests);
-  // NS_LOG_INFO("Total transmitted interests = " << transmittedInterests);
-  // NS_LOG_INFO("Total dropped interests = " << droppedInterests);
-  // NS_LOG_INFO("Total received data = " << receivedData);
-  // NS_LOG_INFO("Total transmitted data = " << transmittedData);
-  // NS_LOG_INFO("Total dropped data = " << droppedData);
-  NS_LOG_INFO (trace);
+  NS_LOG_INFO ("AppTrace: \n" << appTrace);
+  NS_LOG_INFO ("CcnxTrace: \n" << ccnxTrace);
   return 0;
 }
diff --git a/helper/ccnx-stack-helper.cc b/helper/ccnx-stack-helper.cc
index 9699c38..6e2a411 100644
--- a/helper/ccnx-stack-helper.cc
+++ b/helper/ccnx-stack-helper.cc
@@ -200,8 +200,7 @@
   Ptr<CcnxL3Protocol> ccnx = CreateObject<CcnxL3Protocol> ();
   node->AggregateObject (ccnx);
 
-  ccnx->SetForwardingStrategy
-    (DynamicCast<CcnxForwardingStrategy> (m_strategyFactory.Create<Object> ()));
+  ccnx->SetForwardingStrategy (m_strategyFactory.Create<CcnxForwardingStrategy> ());
   
   for (uint32_t index=0; index < node->GetNDevices (); index++)
     {
diff --git a/model/ccnx-bestroute-strategy.cc b/model/ccnx-bestroute-strategy.cc
index b850d08..776315f 100644
--- a/model/ccnx-bestroute-strategy.cc
+++ b/model/ccnx-bestroute-strategy.cc
@@ -19,7 +19,10 @@
  */
 
 #include "ccnx-bestroute-strategy.h"
+
 #include "ccnx-interest-header.h"
+#include "ccnx-pit.h"
+#include "ccnx-pit-entry.h"
 
 #include "ns3/assert.h"
 #include "ns3/log.h"
@@ -96,6 +99,7 @@
                      ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
 
       metricFace.m_face->Send (packet->Copy ());
+      m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
       break; // do only once
diff --git a/model/ccnx-flooding-strategy.cc b/model/ccnx-flooding-strategy.cc
index 4a8dd50..5b8542d 100644
--- a/model/ccnx-flooding-strategy.cc
+++ b/model/ccnx-flooding-strategy.cc
@@ -19,10 +19,13 @@
  */
 
 #include "ccnx-flooding-strategy.h"
+#include "ccnx-interest-header.h"
+#include "ccnx-pit.h"
+#include "ccnx-pit-entry.h"
+
 #include "ns3/assert.h"
 #include "ns3/log.h"
 #include "ns3/simulator.h"
-#include "ccnx-interest-header.h"
 
 #include <boost/ref.hpp>
 #include <boost/foreach.hpp>
@@ -114,6 +117,7 @@
       //   }
 
       metricFace.m_face->Send (packet->Copy ());
+      m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
     }
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 4a1c3a8..d09d916 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -24,6 +24,11 @@
 #include "ccnx-forwarding-strategy.h"
 #include "ns3/log.h"
 #include "ns3/simulator.h"
+#include "ns3/double.h"
+
+#include "ccnx-pit.h"
+#include "ccnx-pit-entry.h"
+
 #include "ccnx-interest-header.h"
 
 #include <boost/ref.hpp>
@@ -45,6 +50,10 @@
   static TypeId tid = TypeId ("ns3::CcnxForwardingStrategy")
     .SetGroupName ("Ccnx")
     .SetParent<Object> ()
+
+    .AddTraceSource ("OutInterests", "Interests that were transmitted",
+                    MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_transmittedInterestsTrace))
+
     ;
   return tid;
 }
@@ -102,6 +111,7 @@
                      ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
 
       metricFace.m_face->Send (packet->Copy ());
+      m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
       break; // propagate only one interest
@@ -117,5 +127,4 @@
   return propagatedCount > 0;
 }
 
-
 } //namespace ns3
diff --git a/model/ccnx-forwarding-strategy.h b/model/ccnx-forwarding-strategy.h
index bb11ec6..73f1165 100644
--- a/model/ccnx-forwarding-strategy.h
+++ b/model/ccnx-forwarding-strategy.h
@@ -24,16 +24,14 @@
 #include "ns3/packet.h"
 #include "ns3/callback.h"
 #include "ns3/object.h"
-
-#include "ccnx.h"
-#include "ccnx-fib.h"
-#include "ccnx-pit.h"
-#include "ccnx-pit-entry.h"
+#include "ns3/traced-callback.h"
 
 namespace ns3 {
 
 class CcnxFace;
 class CcnxInterestHeader;
+class CcnxPit;
+class CcnxPitEntry;
 
 /**
  * \ingroup ccnx
@@ -74,7 +72,7 @@
    */
   void
   SetPit (Ptr<CcnxPit> pit);
-
+  
 protected:
   /**
    * @brief Propage interest vie a green interface. Fail, if no green interfaces available
@@ -93,10 +91,11 @@
                              const Ptr<CcnxFace> &incomingFace,
                              Ptr<CcnxInterestHeader> &header,
                              const Ptr<const Packet> &packet);
+
+  TracedCallback<Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace> > m_transmittedInterestsTrace;
   
 protected:  
   Ptr<CcnxPit> m_pit;
-  Ptr<Ccnx> m_ccnx; // just for tracing purposes. Should not be used in any other way
 };
 
 } //namespace ns3
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index fb1e5e4..4ee61f7 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -80,25 +80,6 @@
                    MakeTimeAccessor (&CcnxL3Protocol::GetBucketLeakInterval,
                                      &CcnxL3Protocol::SetBucketLeakInterval),
                    MakeTimeChecker ())
-
-    .AddTraceSource ("TransmittedInterestTrace", "Interests that were transmitted",
-                    MakeTraceSourceAccessor (&CcnxL3Protocol::m_transmittedInterestsTrace))
-    
-    .AddTraceSource ("ReceivedInterestTrace", "Interests that were received",
-                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_receivedInterestsTrace))
-    
-    .AddTraceSource ("DroppedInterestTrace", "Interests that were dropped",
-                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_droppedInterestsTrace))
-
-    .AddTraceSource ("ReceivedDataTrace", "Data that were received",
-                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_receivedDataTrace))
-    
-    .AddTraceSource ("TransmittedDataTrace", "Data that were transmitted",
-                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_transmittedDataTrace))
-    
-    .AddTraceSource ("DroppedDataTrace", "Data that were dropped",
-                     MakeTraceSourceAccessor (&CcnxL3Protocol::m_droppedDataTrace))
-
   ;
   return tid;
 }
@@ -318,18 +299,17 @@
                         const Ptr<const Packet> &packet)
 {
   NS_LOG_FUNCTION (incomingFace << header << packet);
+  m_inNacks (header, incomingFace);
 
   tuple<const CcnxPitEntry&,bool,bool> ret = m_pit->Lookup (*header);
   CcnxPitEntry const& pitEntry = ret.get<0> ();
   bool isNew = ret.get<1> ();
   bool isDuplicated = ret.get<2> ();
 
-  // NS_ASSERT_MSG (isDuplicated,
-  //                "NACK should be a duplicated interest");
   if (isNew || !isDuplicated) // potential flow
     {
       // somebody is doing something bad
-      m_droppedInterestsTrace (header, NACK_NONDUPLICATE, m_node->GetObject<Ccnx> (), incomingFace);
+      m_dropNacks (header, NON_DUPLICATED, incomingFace);
       return;
     }
   
@@ -342,6 +322,7 @@
                      "Node " << GetObject<Node> ()->GetId () << ", outgoing entry should exist for face " << boost::cref(*incomingFace) << "\n" <<
                      "size: " << pitEntry.m_outgoing.size ());
       
+      // m_dropNacks (header, NON_DUPLICATE, incomingFace);
       return;
     }
 
@@ -371,7 +352,7 @@
   if (pitEntry.m_incoming.size () == 0) // interest was actually satisfied
     {
       // no need to do anything
-      m_droppedInterestsTrace (header, NACK_AFTER_SATISFIED, m_node->GetObject<Ccnx> (), incomingFace);
+      m_dropNacks (header, AFTER_SATISFIED, incomingFace);
       return;
     }
 
@@ -380,7 +361,7 @@
       NS_LOG_DEBUG ("Not all outgoing are in vain");
       // suppress
       // Don't do anything, we are still expecting data from some other face
-      m_droppedInterestsTrace (header, NACK_SUPPRESSED, m_node->GetObject<Ccnx> (), incomingFace);
+      m_dropNacks (header, SUPPRESSED, incomingFace);
       return;
     }
   
@@ -397,7 +378,10 @@
   // // If no interests was propagated, then there is not other option for forwarding or
   // // ForwardingStrategy failed to find it. 
   if (!propagated)
-     GiveUpInterest (pitEntry, header);
+    {
+      m_dropNacks (header, NO_FACES, incomingFace); // this headers doesn't have NACK flag set
+      GiveUpInterest (pitEntry, header);
+    }
 }
 
 // Processing Interests
@@ -409,7 +393,7 @@
                                  const Ptr<const Packet> &packet)
 {
   NS_LOG_FUNCTION (incomingFace << header << packet);
-  //m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> (), incomingFace);
+  m_inInterests (header, incomingFace);
 
   // Lookup of Pit (and associated Fib) entry for this Interest 
   tuple<const CcnxPitEntry&,bool,bool> ret = m_pit->Lookup (*header);
@@ -419,24 +403,22 @@
 
   if (isDuplicated) 
     {
+      m_dropInterests (header, DUPLICATED, incomingFace);
+
       /**
        * This condition will handle "routing" loops and also recently satisfied interests.
        * Every time interest is satisfied, PIT entry (with empty incoming and outgoing faces)
        * is kept for another small chunk of time.
        */
       
-      // //Trace duplicate interest  
-      // m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
-
       NS_LOG_DEBUG ("Sending NACK_LOOP");
       header->SetNack (CcnxInterestHeader::NACK_LOOP);
       Ptr<Packet> nack = Create<Packet> ();
       nack->AddHeader (*header);
 
       incomingFace->Send (nack);
+      m_outNacks (header, incomingFace);
       
-      // //Trace duplicate interest  
-      m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
       return;
     }
 
@@ -449,8 +431,8 @@
       
       NS_LOG_LOGIC("Found in cache");
         
-      m_transmittedDataTrace (contentObjectHeader, contentObject, CACHED, m_node->GetObject<Ccnx> (), incomingFace);
       incomingFace->Send (contentObject);
+      m_outData (contentObjectHeader, true, incomingFace);
 
       // Set pruning timout on PIT entry (instead of deleting the record)
       m_pit->modify (m_pit->iterator_to (pitEntry),
@@ -504,9 +486,8 @@
   if (!isRetransmitted &&
       pitEntry.AreTherePromisingOutgoingFacesExcept (incomingFace))
     { // Suppress this interest if we're still expecting data from some other face
-      
-      // We are already expecting data later in future. Suppress the interest
-      m_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
+
+      m_dropInterests (header, SUPPRESSED, incomingFace);
       return;
     }
   
@@ -534,35 +515,12 @@
   // If no interests was propagated, then there is not other option for forwarding or
   // ForwardingStrategy failed to find it. 
   if (!propagated)
-    GiveUpInterest (pitEntry, header);
-}
-
-void
-CcnxL3Protocol::GiveUpInterest (const CcnxPitEntry &pitEntry,
-                                Ptr<CcnxInterestHeader> header)
-{
-  Ptr<Packet> packet = Create<Packet> ();
-  header->SetNack (CcnxInterestHeader::NACK_GIVEUP_PIT);
-  packet->AddHeader (*header);
-
-  BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
     {
-      incoming.m_face->Send (packet->Copy ());
-
-      //m_droppedInterestsTrace (header, DROP_CONGESTION,
-      //                         m_node->GetObject<Ccnx> (), incomingFace);
+      m_dropInterests (header, NO_FACES, incomingFace);
+      GiveUpInterest (pitEntry, header);
     }
-  // All incoming interests cannot be satisfied. Remove them
-  m_pit->modify (m_pit->iterator_to (pitEntry),
-                 ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
-
-  // Set pruning timout on PIT entry (instead of deleting the record)
-  m_pit->modify (m_pit->iterator_to (pitEntry),
-                 ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
-                           Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
 }
 
-
 // Processing ContentObjects
 void
 CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
@@ -572,7 +530,7 @@
 {
     
   NS_LOG_FUNCTION (incomingFace << header << payload << packet);
-  m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> (), incomingFace);
+  m_inData (header, incomingFace);
 
   // 1. Lookup PIT entry
   try
@@ -617,7 +575,10 @@
       BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
         {
           if (incoming.m_face != incomingFace)
-            incoming.m_face->Send (packet->Copy ());
+            {
+              incoming.m_face->Send (packet->Copy ());
+              m_outData (header, false, incoming.m_face);
+            }
 
           // successfull forwarded data trace
         }
@@ -636,12 +597,36 @@
       //    (unsolicited data packets should not "poison" content store)
       
       //drop dulicated or not requested data packet
-      m_droppedDataTrace (header, payload, NDN_UNSOLICITED_DATA, m_node->GetObject<Ccnx> (), incomingFace);
+      m_dropData (header, UNSOLICITED, incomingFace);
       return; // do not process unsoliced data packets
     }
 }
 
 void
+CcnxL3Protocol::GiveUpInterest (const CcnxPitEntry &pitEntry,
+                                Ptr<CcnxInterestHeader> header)
+{
+  Ptr<Packet> packet = Create<Packet> ();
+  header->SetNack (CcnxInterestHeader::NACK_GIVEUP_PIT);
+  packet->AddHeader (*header);
+
+  BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
+    {
+      incoming.m_face->Send (packet->Copy ());
+
+      m_outNacks (header, incoming.m_face);
+    }
+  // All incoming interests cannot be satisfied. Remove them
+  m_pit->modify (m_pit->iterator_to (pitEntry),
+                 ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
+
+  // Set pruning timout on PIT entry (instead of deleting the record)
+  m_pit->modify (m_pit->iterator_to (pitEntry),
+                 ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
+                           Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+}
+
+void
 CcnxL3Protocol::SetBucketLeakInterval (Time interval)
 {
   m_bucketLeakInterval = interval;
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 29500fc..8ac24d6 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -26,7 +26,6 @@
 #include <stdint.h>
 #include "ns3/ptr.h"
 #include "ns3/net-device.h"
-#include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
 #include "ns3/simulator.h"
 
@@ -87,36 +86,6 @@
   virtual ~CcnxL3Protocol ();
 
   /**
-   * \enum DropReason
-   * \brief Reason why a packet has been dropped.
-   */
-  enum DropReason 
-  {
-    NDN_DUPLICATE_INTEREST,  ///< \brief Duplicate Interest
-    NDN_SUPPRESSED_INTEREST, ///< \brief Suppressed Interest
-    NDN_UNSOLICITED_DATA,    ///< \brief Unsolicited ContentObject(duplicate?)
-    NDN_PIT_TIMER_EXPIRED,
-    INTERFACE_DOWN,          ///< \brief Interface is down
-
-    NACK_SUPPRESSED,
-    NACK_AFTER_SATISFIED,
-    NACK_NONDUPLICATE,
-
-    DROP_NO_ROUTE,   /**< No route to host */
-  };    
-
-  /**
-   * \enum DropReason
-   * \brief Description of where content object was originated
-   */
-  enum ContentObjectSource
-  {
-    APPLICATION,
-    FORWARDED,
-    CACHED
-  };
-
-  /**
    * \brief Assigns node to the CCNx stack
    *
    * \param node Simulation node
@@ -243,29 +212,6 @@
 
   Time    m_bucketLeakInterval;
   EventId m_bucketLeakEvent;
-  
-  TracedCallback<Ptr<const CcnxInterestHeader>,
-                 Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedInterestsTrace;
-  
-  TracedCallback<Ptr<const CcnxInterestHeader>,
-                 Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedInterestsTrace;
-  
-  TracedCallback<Ptr<const CcnxInterestHeader>,
-                 DropReason,
-                 Ptr<Ccnx>, Ptr<const CcnxFace> > m_droppedInterestsTrace;
-
-  TracedCallback<Ptr<const CcnxContentObjectHeader>,
-                 Ptr<const Packet>,/*payload*/
-                 Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedDataTrace;
-
-  TracedCallback<Ptr<const CcnxContentObjectHeader>,
-                  Ptr<const Packet>,/*payload*/
-                  ContentObjectSource,
-                  Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedDataTrace;
-  TracedCallback<Ptr<const CcnxContentObjectHeader>,
-                  Ptr<const Packet>,/*payload*/
-                  DropReason,
-                  Ptr<Ccnx>, Ptr<const CcnxFace> > m_droppedDataTrace;
 };
   
 } // Namespace ns3
diff --git a/model/ccnx.cc b/model/ccnx.cc
index af551a6..30b290e 100644
--- a/model/ccnx.cc
+++ b/model/ccnx.cc
@@ -23,6 +23,10 @@
 #include "ns3/boolean.h"
 
 #include "ccnx.h"
+#include "ccnx-face.h"
+#include "ccnx-forwarding-strategy.h"
+#include "ccnx-interest-header.h"
+#include "ccnx-content-object-header.h"
 
 namespace ns3 {
 
@@ -34,6 +38,29 @@
   static TypeId tid = TypeId ("ns3::Ccnx")
     .SetGroupName ("Ccnx")
     .SetParent<Object> ()
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
+
+    // "OutInterests" trace is inside CcnxForwardingStrategy
+    .AddTraceSource ("InInterests",   "InInterests",   MakeTraceSourceAccessor (&Ccnx::m_inInterests))
+    .AddTraceSource ("DropInterests", "DropInterests", MakeTraceSourceAccessor (&Ccnx::m_dropInterests))
+    
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
+
+    .AddTraceSource ("OutNacks",  "OutNacks",  MakeTraceSourceAccessor (&Ccnx::m_outNacks))
+    .AddTraceSource ("InNacks",   "InNacks",   MakeTraceSourceAccessor (&Ccnx::m_inNacks))
+    .AddTraceSource ("DropNacks", "DropNacks", MakeTraceSourceAccessor (&Ccnx::m_dropNacks))
+    
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
+
+    .AddTraceSource ("OutData",  "OutData",  MakeTraceSourceAccessor (&Ccnx::m_outData))
+    .AddTraceSource ("InData",   "InData",   MakeTraceSourceAccessor (&Ccnx::m_inData))
+    .AddTraceSource ("DropData", "DropData", MakeTraceSourceAccessor (&Ccnx::m_dropData))
+    
+    ////////////////////////////////////////////////////////////////////
+    ////////////////////////////////////////////////////////////////////
   ;
   return tid;
 }
diff --git a/model/ccnx.h b/model/ccnx.h
index 38c2f74..f87da94 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -23,6 +23,7 @@
 
 #include "ns3/object.h"
 #include "ns3/callback.h"
+#include "ns3/traced-callback.h"
 
 namespace ns3 {
 
@@ -79,13 +80,6 @@
 class Ccnx : public Object
 {
 public:
-  enum ForwardingStrategy
-    { 
-      NDN_FLOODING = 1,
-      NDN_BESTROUTE = 2,
-      NDN_RANKING = 3 
-    };
-
   /**
    * \brief Interface ID
    *
@@ -94,48 +88,6 @@
   static TypeId GetTypeId ();
   virtual ~Ccnx ();
 
-  // /**
-  //  * \brief Send an Interest packet to a specified face
-  //  *
-  //  * \param face face where to send this packet
-  //  * \param header Interest header
-  //  * \param packet fully prepared CCNx packet to send
-  //  *
-  //  * Higher-level layers (forwarding strategy in particular) call this
-  //  * method to send a packet down the stack to the MAC and PHY layers.
-  //  */
-  // virtual void
-  // SendInterest (const Ptr<CcnxFace> &face,
-  //               const Ptr<const CcnxInterestHeader> &header,
-  //               const Ptr<Packet> &packet) = 0;
-
-  // /**
-  //  * \brief Send a ContentObject packet to a specified face
-  //  *
-  //  * \param face face where to send this packet
-  //  * \param header ContentObject header
-  //  * \param packet fully prepared CCNx packet to send
-  //  *
-  //  * Higher-level layers (forwarding strategy in particular) call this
-  //  * method to send a packet down the stack to the MAC and PHY layers.
-  //  */
-  // virtual void
-  // SendContentObject (const Ptr<CcnxFace> &face,
-  //                    const Ptr<const CcnxContentObjectHeader> &header,
-  //                    const Ptr<Packet> &packet) = 0;
-
-  // /**
-  //  * \brief Lower layers calls this method after demultiplexing
-  //  *
-  //  * Lower-layer-dependent implementation of CcnxFace will do actual work
-  //  * to set up demultiplexing and call this function as a callback
-  //  *
-  //  * \param face face from which packet came from
-  //  * \param p the packet
-  //  */
-  // virtual void
-  // Receive (const Ptr<CcnxFace> &face, const Ptr<const Packet> &p) = 0;
-
   /**
    * \brief Register a new forwarding strategy to be used by this Ccnx
    * stack
@@ -197,6 +149,64 @@
    */
   virtual Ptr<CcnxFace>
   GetFaceByNetDevice (Ptr<NetDevice> netDevice) const = 0;
+
+
+  /**
+   * \enum DropReason
+   * \brief A reason why the packet has been dropped
+   */
+  enum DropReason
+    {
+      DUPLICATED, // Interests
+      SUPPRESSED, // Interests and Nacks
+      NO_FACES,    // Interests
+      NON_DUPLICATED, // Nacks
+      AFTER_SATISFIED, // Nacks
+      UNSOLICITED      // data
+    };
+  
+protected:
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  
+  // transmittedInterestTrace is inside ForwardingStrategy
+  
+  TracedCallback<Ptr<const CcnxInterestHeader>,
+                 Ptr<const CcnxFace> > m_inInterests;
+
+  TracedCallback<Ptr<const CcnxInterestHeader>,
+                 DropReason,
+                 Ptr<const CcnxFace> > m_dropInterests;
+  
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+
+  TracedCallback<Ptr<const CcnxInterestHeader>,
+                 Ptr<const CcnxFace> > m_outNacks;
+
+  TracedCallback<Ptr<const CcnxInterestHeader>,
+                 Ptr<const CcnxFace> > m_inNacks;
+
+  TracedCallback<Ptr<const CcnxInterestHeader>,
+                 DropReason,
+                 Ptr<const CcnxFace> > m_dropNacks;
+
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+
+  TracedCallback<Ptr<const CcnxContentObjectHeader>,
+                 bool /*from cache*/,
+                 Ptr<const CcnxFace> > m_outData;
+
+  TracedCallback<Ptr<const CcnxContentObjectHeader>,
+                 Ptr<const CcnxFace> > m_inData;
+
+  TracedCallback<Ptr<const CcnxContentObjectHeader>,
+                  DropReason,
+                  Ptr<const CcnxFace> > m_dropData;  
 };
 
 } // namespace ns3