Tracing
diff --git a/examples/abilene-topology.cc b/examples/abilene-topology.cc
index a96daf7..c0c1f16 100644
--- a/examples/abilene-topology.cc
+++ b/examples/abilene-topology.cc
@@ -26,6 +26,7 @@
 #include "ns3/point-to-point-grid.h"
 #include "ns3/ipv4-global-routing-helper.h"
 #include "ns3/animation-interface.h"
+#include "ns3/ccnx-l3-protocol.h"
 
 #include <iostream>
 #include <sstream>
@@ -37,6 +38,14 @@
 
 NS_LOG_COMPONENT_DEFINE ("CcnxAbileneTopology");
 
+int transmittedInterests = 0;
+int receivedInterests = 0;
+int droppedInterests = 0;
+
+int transmittedData = 0;
+int receivedData = 0;
+int droppedData = 0;
+
 void PrintTime ()
 {
   NS_LOG_INFO (Simulator::Now ());
@@ -60,11 +69,47 @@
     }
 }
 
+static void OnTransmittedInterest (std::string context, Ptr<const CcnxInterestHeader> header, 
+                                   Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
+{
+  transmittedInterests++;
+}
+
+static void OnReceivedInterest (std::string context, Ptr<const CcnxInterestHeader> header, 
+                                Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
+{
+  receivedInterests++;
+}
+
+static void OnDroppedInterest (std::string context, Ptr<const CcnxInterestHeader> header, CcnxL3Protocol::DropReason reason,
+                               Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
+{
+  droppedInterests++;
+}
+
+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++;    
+}
+
+static void OnReceivedData (std::string context, Ptr<const CcnxContentObjectHeader> header, Ptr<const Packet> packet,
+                            Ptr<Ccnx> ccnx, Ptr<const CcnxFace> face)
+{
+    receivedData++;
+}
+
+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++;
+}
+
 int 
 main (int argc, char *argv[])
 {
-  // Packet::EnableChecking();
-  // Packet::EnablePrinting();
+  Packet::EnableChecking();
+  Packet::EnablePrinting();
   string input ("./src/NDNabstraction/examples/abilene-topology.txt");
     
   Time finishTime = Seconds (20.0);
@@ -92,6 +137,13 @@
       return -1;
     }
 
+  int droppedInterests[nodes.GetN()];
+  int congestedInterests[nodes.GetN()];
+  int sentInterests[nodes.GetN()];
+  (void)droppedInterests;
+  (void)sentInterests;
+  (void)congestedInterests;
+    
   SpringMobilityHelper::InstallSprings (reader.LinksBegin (), reader.LinksEnd ());
 
   // InternetStackHelper stack;
@@ -137,9 +189,38 @@
       anim->SetMobilityPollInterval (Seconds (1));
     }
 
+  NS_LOG_INFO ("Configure Tracing.");
+  // first, pcap tracing in non-promiscuous mode
+  //ccnxHelper.EnablePcapAll ("csma-ping", false);
+  // then, print what the packet sink receives.
+  //Config::ConnectWithoutContext ("/NodeList/3/ApplicationList/0/$ns3::PacketSink/Rx", 
+  //                                 MakeCallback (&SinkRx));
+  // finally, print the ping rtts.
+    //Packet::EnablePrinting ();
+  Config::Connect("/NodeList/*/ns3::CcnxL3Protocol/TransmittedInterestTrace",
+                                 MakeCallback (&OnTransmittedInterest));
+  Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/ReceivedInterestTrace",
+                     MakeCallback (&OnReceivedInterest));
+  Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/DroppedInterestTrace",
+                     MakeCallback (&OnDroppedInterest));
+    
+  Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/ReceivedDataTrace",
+                     MakeCallback (&OnReceivedData));
+  Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/TransmittedDataTrace",
+                     MakeCallback (&OnTransmittedData));
+  Config::Connect ("/NodeList/*/ns3::CcnxL3Protocol/DroppedDataTrace",
+                     MakeCallback (&OnDroppedData));
+
   NS_LOG_INFO ("Run Simulation.");
   Simulator::Run ();
   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);
   return 0;
 }
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index bffc917..6b567c8 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -69,6 +69,25 @@
                    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;
 }
@@ -240,7 +259,43 @@
   if (!face->IsUp ())
     {
       NS_LOG_LOGIC ("Dropping received packet -- interface is down");
-      // m_dropTrace (p, INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
+        
+      //m_droppedDTrace (p, INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
+        
+        Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
+        try
+        {
+            CcnxHeaderHelper::Type type = CcnxHeaderHelper::GetCcnxHeaderType (p);
+            switch (type)
+            {
+                case CcnxHeaderHelper::INTEREST:
+                {
+                    Ptr<CcnxInterestHeader> header = Create<CcnxInterestHeader> ();
+                    m_droppedInterestsTrace (header, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
+                    break;
+                }
+                case CcnxHeaderHelper::CONTENT_OBJECT:
+                {
+                    Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
+                    
+                    static CcnxContentObjectTail contentObjectTrailer; //there is no data in this object
+                    
+                    // Deserialization. Exception may be thrown
+                    packet->RemoveHeader (*header);
+                    packet->RemoveTrailer (contentObjectTrailer);
+                    
+                    m_droppedDataTrace (header, packet, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
+                    break;
+                }
+            }
+            
+            // exception will be thrown if packet is not recognized
+        }
+        catch (CcnxUnknownHeaderException)
+        {
+            NS_ASSERT_MSG (false, "Unknown CCNx header. Should not happen");
+        }
+        
       return;
     }
   NS_LOG_LOGIC ("Packet from face " << *face << " received on node " <<  m_node->GetId ());
@@ -305,6 +360,7 @@
   if (isNew || !isDuplicated) // potential flow
     {
       // somebody is doing something bad
+      m_droppedInterestsTrace (header, NACK_NONDUPLICATE, m_node->GetObject<Ccnx> (), incomingFace);
       return;
     }
   
@@ -329,8 +385,6 @@
 
   m_pit->modify (m_pit->iterator_to (pitEntry),
                  ll::bind (&CcnxPitEntry::SetWaitingInVain, ll::_1, outFace));
-  
-  // m_droppedInterestsTrace (header, DROP_CONGESTION, m_node->GetObject<Ccnx> (), incomingFace);
 
   // If NACK is NACK_GIVEUP_PIT, then neighbor gave up trying to and removed it's PIT entry.
   // So, if we had an incoming entry to this neighbor, then we can remove it now
@@ -348,6 +402,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);
       return;
     }
 
@@ -356,6 +411,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);
       return;
     }
   
@@ -384,7 +440,7 @@
                                  const Ptr<const Packet> &packet)
 {
   NS_LOG_FUNCTION (incomingFace << header << packet);
-  // m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> (), incomingFace);
+  //m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> (), incomingFace);
 
   // Lookup of Pit (and associated Fib) entry for this Interest 
   tuple<const CcnxPitEntry&,bool,bool> ret = m_pit->Lookup (*header);
@@ -411,7 +467,7 @@
       incomingFace->Send (nack);
       
       // //Trace duplicate interest  
-      // m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
+      m_droppedInterestsTrace (header, NDN_DUPLICATE_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
       return;
     }
 
@@ -424,14 +480,14 @@
       
       NS_LOG_LOGIC("Found in cache");
         
-      // TransmittedDataTrace (contentObject, CACHED,
-      //                       m_node->GetObject<Ccnx> (), incomingFace);
+      m_transmittedDataTrace (contentObjectHeader, contentObject, CACHED, m_node->GetObject<Ccnx> (), incomingFace);
       incomingFace->Send (contentObject);
 
       // Set pruning timout on PIT entry (instead of deleting the record)
       m_pit->modify (m_pit->iterator_to (pitEntry),
                      bind (&CcnxPitEntry::SetExpireTime, ll::_1,
                            Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+        
       return;
     }
 
@@ -481,7 +537,7 @@
     { // 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_droppedInterestsTrace (header, NDN_SUPPRESSED_INTEREST, m_node->GetObject<Ccnx> (), incomingFace);
       return;
     }
   
@@ -524,8 +580,8 @@
     {
       incoming.m_face->Send (packet->Copy ());
 
-      // m_droppedInterestsTrace (header, DROP_CONGESTION,
-      //                          m_node->GetObject<Ccnx> (), incomingFace);
+      //m_droppedInterestsTrace (header, DROP_CONGESTION,
+      //                         m_node->GetObject<Ccnx> (), incomingFace);
     }
   // All incoming interests cannot be satisfied. Remove them
   m_pit->modify (m_pit->iterator_to (pitEntry),
@@ -547,7 +603,7 @@
 {
     
   NS_LOG_FUNCTION (incomingFace << header << payload << packet);
-  // m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
+  m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> (), incomingFace);
 
   // 1. Lookup PIT entry
   try
@@ -611,7 +667,7 @@
       //    (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_droppedDataTrace (header, payload, NDN_UNSOLICITED_DATA, m_node->GetObject<Ccnx> (), incomingFace);
       return; // do not process unsoliced data packets
     }
 }
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 13bdf94..d55ccd4 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -94,13 +94,18 @@
   {
     NDN_DUPLICATE_INTEREST,  ///< \brief Duplicate Interest
     NDN_SUPPRESSED_INTEREST, ///< \brief Suppressed Interest
-    NDN_UNSOLICITED_DATA,    ///< \brief Unsolicited ContentObject (duplicate?)
+    NDN_UNSOLICITED_DATA,    ///< \brief Unsolicited ContentObject(duplicate?)
     NDN_PIT_TIMER_EXPIRED,
     INTERFACE_DOWN,          ///< \brief Interface is down
 
-    DROP_CONGESTION, /**< Congestion detected */
+    NACK_SUPPRESSED,
+    NACK_AFTER_SATISFIED,
+    NACK_NONDUPLICATE,
+
     DROP_NO_ROUTE,   /**< No route to host */
   };
+    
+    
 
   /**
    * \enum DropReason
@@ -241,25 +246,25 @@
   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 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;
+  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