Change in CcnxApp API.  Now callbacks also contain pointer of original
packet (useful to get packet tags, if they exist)

Reflecting changes in PackegTag API

Rescanning bindings

More work on packet-path-weight tracers
diff --git a/model/annotated-topology-reader.cc b/model/annotated-topology-reader.cc
index db8392d..345c2f5 100644
--- a/model/annotated-topology-reader.cc
+++ b/model/annotated-topology-reader.cc
@@ -112,7 +112,7 @@
   return m_nodes;
 }
 
-std::list<TopologyReader::Link>
+const std::list<TopologyReader::Link>&
 AnnotatedTopologyReader::GetLinks () const
 {
   return m_linksList;
diff --git a/model/annotated-topology-reader.h b/model/annotated-topology-reader.h
index eccbc29..6edcb34 100644
--- a/model/annotated-topology-reader.h
+++ b/model/annotated-topology-reader.h
@@ -65,7 +65,7 @@
   /**
    * \brief Get links read by the reader
    */  
-  std::list<Link>
+  const std::list<Link>&
   GetLinks () const;
   
   /**
diff --git a/model/ccnx-bestroute-strategy.cc b/model/ccnx-bestroute-strategy.cc
index 4bb8199..e8be345 100644
--- a/model/ccnx-bestroute-strategy.cc
+++ b/model/ccnx-bestroute-strategy.cc
@@ -23,6 +23,7 @@
 #include "ccnx-interest-header.h"
 #include "ccnx-pit.h"
 #include "ccnx-pit-entry.h"
+#include "ccnx-path-stretch-tag.h"
 
 #include "ns3/assert.h"
 #include "ns3/log.h"
@@ -101,15 +102,11 @@
       m_pit->modify (m_pit->iterator_to (pitEntry),
                      ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
 
-      //update path stretch
-      WeightsPathStretchTag pathStretch;
-      //packet->PeekPacketTag(pathStretch);
-      
-      pathStretch.AddNewHop(metricFace.m_routingCost);
-      packet->AddPacketTag(pathStretch);
+      Ptr<Packet> packetToSend = packet->Copy ();
+      TagPacket (packetToSend, metricFace);
 
       //transmission
-      metricFace.m_face->Send (packet->Copy ());
+      metricFace.m_face->Send (packetToSend);
       m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
diff --git a/model/ccnx-face.cc b/model/ccnx-face.cc
index 77122e0..b1f7b42 100644
--- a/model/ccnx-face.cc
+++ b/model/ccnx-face.cc
@@ -94,6 +94,12 @@
   return *this;
 }
 
+Ptr<Node>
+CcnxFace::GetNode () const
+{
+  return m_node;
+}
+
 void
 CcnxFace::RegisterProtocolHandler (ProtocolHandler handler)
 {
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index df488dc..29ec371 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -67,6 +67,9 @@
   CcnxFace (Ptr<Node> node);
   virtual ~CcnxFace();
 
+  Ptr<Node>
+  GetNode () const;
+
   ////////////////////////////////////////////////////////////////////
   
   /**
diff --git a/model/ccnx-flooding-strategy.cc b/model/ccnx-flooding-strategy.cc
index 27133b4..2a7f2ee 100644
--- a/model/ccnx-flooding-strategy.cc
+++ b/model/ccnx-flooding-strategy.cc
@@ -22,6 +22,7 @@
 #include "ccnx-interest-header.h"
 #include "ccnx-pit.h"
 #include "ccnx-pit-entry.h"
+#include "ccnx-path-stretch-tag.h"
 
 #include "ns3/assert.h"
 #include "ns3/log.h"
@@ -116,16 +117,11 @@
       //     NS_LOG_ERROR ("size: " << pitEntry.m_outgoing.size ());
       //   }
 
+      Ptr<Packet> packetToSend = packet->Copy ();
+      TagPacket (packetToSend, metricFace);
 
-      //update path stretch
-      WeightsPathStretchTag pathStretch;
-      //packet->PeekPacketTag(pathStretch);
-      
-      pathStretch.AddNewHop(metricFace.m_routingCost);
-      packet->AddPacketTag(pathStretch);
-      
       //transmission
-      metricFace.m_face->Send (packet->Copy ());
+      metricFace.m_face->Send (packetToSend);
       m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 1253571..45e0fd7 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -22,14 +22,17 @@
 #include "ns3/assert.h"
 
 #include "ccnx-forwarding-strategy.h"
+#include "ns3/ptr.h"
 #include "ns3/log.h"
 #include "ns3/simulator.h"
 #include "ns3/double.h"
+#include "ns3/boolean.h"
 
 #include "ccnx-pit.h"
 #include "ccnx-pit-entry.h"
 
 #include "ccnx-interest-header.h"
+#include "ccnx-path-stretch-tag.h"
 
 #include <boost/ref.hpp>
 #include <boost/foreach.hpp>
@@ -51,6 +54,11 @@
     .SetGroupName ("Ccnx")
     .SetParent<Object> ()
 
+    .AddAttribute ("MetricTagging", "Enable metric tagging (path-stretch calculation)",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&CcnxForwardingStrategy::m_enableMetricTagging),
+                   MakeBooleanChecker ())
+
     .AddTraceSource ("OutInterests", "Interests that were transmitted",
                     MakeTraceSourceAccessor (&CcnxForwardingStrategy::m_transmittedInterestsTrace))
 
@@ -59,6 +67,7 @@
 }
 
 CcnxForwardingStrategy::CcnxForwardingStrategy ()
+  : m_enableMetricTagging (false)
 {
 }
 
@@ -109,31 +118,43 @@
         }
 
       m_pit->modify (m_pit->iterator_to (pitEntry),
-                     ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
+                     ll::bind (&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
 
-      //update path stretch
-      WeightsPathStretchTag pathStretch;
-      //packet->PeekPacketTag(pathStretch);
-      
-      pathStretch.AddNewHop(metricFace.m_routingCost);
-      packet->AddPacketTag(pathStretch);
+      Ptr<Packet> packetToSend = packet->Copy ();
+      TagPacket (packetToSend, metricFace);
 
       //transmission
-      metricFace.m_face->Send (packet->Copy ());
+      metricFace.m_face->Send (packetToSend);
       m_transmittedInterestsTrace (header, metricFace.m_face);
       
       propagatedCount++;
       break; // propagate only one interest
     }
 
-  // if (Simulator::GetContext ()==1)
-  //   {
-  //     if (propagatedCount > 0)
-  //       NS_LOG_DEBUG ("Propagate via a green face");
-  //     else 
-  //       NS_LOG_DEBUG ("Can't :(");
-  //   }
   return propagatedCount > 0;
 }
 
+void
+CcnxForwardingStrategy::TagPacket (Ptr<Packet> packet, const CcnxFibFaceMetric &metricFace)
+{
+  // if (m_enableMetricTagging)
+    {
+      // update path information
+
+      Ptr<const WeightsPathStretchTag> origTag = packet->RemovePacketTag<WeightsPathStretchTag> ();
+      Ptr<WeightsPathStretchTag> tag;
+      if (origTag == 0)
+        {
+          tag = CreateObject<WeightsPathStretchTag> (); // create a new tag
+        }
+      else
+        {
+          tag = CreateObject<WeightsPathStretchTag> (*origTag); // will update existing tag
+        }
+
+      tag->AddPathInfo (metricFace.m_face->GetNode (), metricFace.m_routingCost);
+      packet->AddPacketTag (tag);
+    }
+}
+
 } //namespace ns3
diff --git a/model/ccnx-forwarding-strategy.h b/model/ccnx-forwarding-strategy.h
index ed9cd82..7be0450 100644
--- a/model/ccnx-forwarding-strategy.h
+++ b/model/ccnx-forwarding-strategy.h
@@ -25,7 +25,6 @@
 #include "ns3/callback.h"
 #include "ns3/object.h"
 #include "ns3/traced-callback.h"
-#include "ccnx-path-stretch-tag.h"
 
 namespace ns3 {
 
@@ -33,6 +32,7 @@
 class CcnxInterestHeader;
 class CcnxPit;
 class CcnxPitEntry;
+class CcnxFibFaceMetric;
 
 /**
  * \ingroup ccnx
@@ -93,10 +93,14 @@
                              Ptr<CcnxInterestHeader> &header,
                              const Ptr<const Packet> &packet);
 
+  void
+  TagPacket (Ptr<Packet> packet, const CcnxFibFaceMetric &metricFace);
+  
   TracedCallback<Ptr<const CcnxInterestHeader>, Ptr<const CcnxFace> > m_transmittedInterestsTrace;
   
 protected:  
   Ptr<CcnxPit> m_pit;
+  bool m_enableMetricTagging; 
 };
 
 } //namespace ns3
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index d6391c5..223c578 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -236,16 +236,6 @@
   return 0;
 }
 
-Ptr<NetDevice>
-CcnxL3Protocol::GetNetDeviceByFace(Ptr<CcnxFace> face) const
-{
-    Ptr<CcnxNetDeviceFace> netDeviceFace = DynamicCast<CcnxNetDeviceFace> (face);
-    if (netDeviceFace == 0) 
-      return 0;
-
-    return netDeviceFace->GetNetDevice ();
-}
-
 uint32_t 
 CcnxL3Protocol::GetNFaces (void) const
 {
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index f4b8f61..86743ac 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -118,9 +118,6 @@
   virtual Ptr<CcnxFace>
   GetFaceByNetDevice (Ptr<NetDevice> netDevice) const;
   
-  virtual Ptr<NetDevice>
-  GetNetDeviceByFace (Ptr<CcnxFace> face) const;
-  
   Ptr<CcnxPit> GetPit();
   
   // void ScheduleLeakage();
@@ -210,7 +207,7 @@
   Ptr<CcnxPit> m_pit; ///< \brief PIT (pending interest table)
   Ptr<CcnxFib> m_fib; ///< \brief FIB  
   Ptr<CcnxContentStore> m_contentStore; ///< \brief Content store (for caching purposes only)
-  
+
   // Time    m_bucketLeakInterval;
   // EventId m_bucketLeakEvent;
 };
diff --git a/model/ccnx-local-face.cc b/model/ccnx-local-face.cc
index fe7271f..404e38f 100644
--- a/model/ccnx-local-face.cc
+++ b/model/ccnx-local-face.cc
@@ -26,12 +26,14 @@
 #include "ns3/packet.h"
 #include "ns3/node.h"
 #include "ns3/assert.h"
+#include "ns3/simulator.h"
 
 #include "ns3/ccnx-header-helper.h"
 #include "ns3/ccnx-app.h"
 
 #include "ccnx-interest-header.h"
 #include "ccnx-content-object-header.h"
+#include "ccnx-path-stretch-tag.h"
 
 NS_LOG_COMPONENT_DEFINE ("CcnxLocalFace");
 
@@ -44,8 +46,8 @@
   static TypeId tid = TypeId ("ns3::CcnxLocalFace")
     .SetParent<CcnxFace> ()
     .SetGroupName ("Ccnx")
-    .AddTraceSource ("ReceivedPathStretchTags", "ReceivedPathStretchTags",
-                    MakeTraceSourceAccessor (&CcnxLocalFace::m_receivedPathStretchTags))
+    .AddTraceSource ("PathWeightsTrace", "PathWeightsTrace",
+                    MakeTraceSourceAccessor (&CcnxLocalFace::m_pathWeightsTrace))
     ;
   return tid;
 }
@@ -89,11 +91,20 @@
 
   m_app->RegisterProtocolHandler (MakeCallback (&CcnxFace::Receive, this));
 }
-    
+
 void
 CcnxLocalFace::SendImpl (Ptr<Packet> p)
 {
   NS_LOG_FUNCTION (this << p);
+  std::cout << Simulator::Now () << ", " << m_app->GetInstanceTypeId ().GetName () << "\n";
+
+  // Notify trace about path weights vector (e.g., for path-stretch calculation)
+  Ptr<const WeightsPathStretchTag> tag = p->RemovePacketTag<WeightsPathStretchTag> ();
+  if (tag != 0)
+    {
+      m_pathWeightsTrace (tag->GetTotalWeight (), tag->GetSourceNode (), m_app->GetNode ());
+      std::cout << boost::cref(*tag) << "\n";
+    }
 
   try
     {
@@ -106,21 +117,9 @@
             p->RemoveHeader (*header);
 
             if (header->GetNack () > 0)
-              m_app->OnNack (header);
+              m_app->OnNack (header, p);
             else
-              {
-                WeightsPathStretchTag totalStretch;
-                
-                WeightsPathStretchTag pathStretch;
-                while(p->RemovePacketTag(pathStretch) == true)
-                {
-                    totalStretch.AddNewHop (pathStretch.GetValue ());
-                }
-                
-                m_receivedPathStretchTags (totalStretch,header,m_app);
-                
-                m_app->OnInterest (header);
-              }
+              m_app->OnInterest (header, p);
           
             break;
           }
diff --git a/model/ccnx-local-face.h b/model/ccnx-local-face.h
index b1d5478..507f8b1 100644
--- a/model/ccnx-local-face.h
+++ b/model/ccnx-local-face.h
@@ -24,7 +24,6 @@
 
 #include "ccnx-face.h"
 #include "ns3/traced-callback.h"
-#include "ccnx-path-stretch-tag.h"
 
 namespace ns3 
 {
@@ -78,8 +77,7 @@
 private:
   Ptr<CcnxApp> m_app;
   
-  TracedCallback<WeightsPathStretchTag,Ptr<const CcnxInterestHeader>, 
-                  Ptr<CcnxApp> > m_receivedPathStretchTags;
+  TracedCallback<uint32_t, Ptr<Node>, Ptr<Node> > m_pathWeightsTrace;
 };
 
 std::ostream& operator<< (std::ostream& os, const CcnxLocalFace &localFace);
diff --git a/model/ccnx-path-stretch-tag.cc b/model/ccnx-path-stretch-tag.cc
index f2759be..b4b29e1 100644
--- a/model/ccnx-path-stretch-tag.cc
+++ b/model/ccnx-path-stretch-tag.cc
@@ -19,74 +19,93 @@
  */
  
 #include "ccnx-path-stretch-tag.h"
+#include "ns3/node.h"
+#include "ns3/names.h"
 
 namespace ns3 {
 
-WeightsPathStretchTag::WeightsPathStretchTag()
-    : m_weightPathStretch(0)
+WeightsPathStretchTag::WeightsPathStretchTag ()
 {
 }
 
-WeightsPathStretchTag::WeightsPathStretchTag(const WeightsPathStretchTag &o)
-    : m_weightPathStretch(o.m_weightPathStretch)
+void
+WeightsPathStretchTag::AddPathInfo (Ptr<Node> node, uint32_t weight)
 {
+  m_infos.push_back (NodeWeightPair (node, weight));
 }
 
-WeightsPathStretchTag &WeightsPathStretchTag::operator = (const WeightsPathStretchTag &o)
-{
-    if (this == &o)
-        return *this;
 
-    m_weightPathStretch = o.m_weightPathStretch;
-    return *this;
+TypeId WeightsPathStretchTag::GetTypeId ()
+{
+  static TypeId tid = TypeId("ns3::WeightsPathStretchTag")
+    .SetParent<Tag>()
+    .AddConstructor<WeightsPathStretchTag>()
+    ;
+  return tid;
 }
 
-bool WeightsPathStretchTag::operator == (WeightsPathStretchTag const &o) const
+// TypeId
+// WeightsPathStretchTag::GetInstanceTypeId () const
+// {
+//   return GetTypeId ();
+// }
+
+uint32_t
+WeightsPathStretchTag::GetTotalWeight () const
 {
-    return (m_weightPathStretch == o.m_weightPathStretch);
+  uint32_t total = 0;
+  for (std::list<NodeWeightPair>::const_iterator info = m_infos.begin (); info != m_infos.end (); info++)
+    {
+      total += info->weight;
+    }
+  return total;
 }
 
-TypeId WeightsPathStretchTag::GetTypeId(void)
+Ptr<Node>
+WeightsPathStretchTag::GetSourceNode () const
 {
-    static TypeId tid = TypeId("ns3::WeightsPathStretchTag")
-        .SetParent<Tag>()
-        .AddConstructor<WeightsPathStretchTag>()
-        ;
-    return tid;
+  NS_ASSERT (m_infos.size () > 0);
+  return m_infos.front ().node;
 }
 
-TypeId WeightsPathStretchTag::GetInstanceTypeId(void) const
+uint32_t WeightsPathStretchTag::GetSerializedSize (void) const
 {
-    return GetTypeId();
+  return 0;
+  // return sizeof (GetPointer (m_value.node)) + sizeof (m_value.weight);
 }
 
-uint32_t WeightsPathStretchTag::GetSerializedSize(void) const
+void WeightsPathStretchTag::Serialize (TagBuffer i) const
 {
-    return sizeof(uint32_t);
+  NS_FATAL_ERROR ("Serialization is not supported for this tag");
+  // m_value.node->Ref ();
+  // i.WriteU64 (reinterpret_cast<uint64_t> (GetPointer (m_value.node)));
+  // i.WriteU32 (m_value.weight);
 }
 
-void WeightsPathStretchTag::Serialize(TagBuffer i) const
+void WeightsPathStretchTag::Deserialize (TagBuffer i)
 {
-    i.WriteU32(m_weightPathStretch);
+  NS_FATAL_ERROR ("Deserialization is not supported for this tag");
+  // m_value.node = Ptr<Node> (reinterpret_cast<Node*> (i.ReadU64 ()), false);
+  // m_value.weight = i.ReadU32 ();
 }
 
-void WeightsPathStretchTag::Deserialize(TagBuffer i)
+void WeightsPathStretchTag::Print (std::ostream &os) const
 {
-    m_weightPathStretch = i.ReadU32();
+  for (std::list<NodeWeightPair>::const_iterator info = m_infos.begin ();
+       info != m_infos.end ();
+       info ++)
+    {
+      if (info != m_infos.begin ()) os << ",";
+      NS_ASSERT (info->node != 0);
+
+      std::string name = Names::FindName (info->node);
+      if (!name.empty ())
+        os << name;
+      else
+        os << info->node->GetId ();
+      os << ":" << info->weight;
+    }
 }
 
-void WeightsPathStretchTag::Print(std::ostream &os) const
-{
-    os << "Path Stretch (Weights) = " << m_weightPathStretch << std::endl;
-}
-
-void WeightsPathStretchTag::AddNewHop(uint32_t weight)
-{
-    m_weightPathStretch +=weight;
-}
-uint32_t WeightsPathStretchTag::GetValue()
-{
-  return m_weightPathStretch;
-}
 } // namespace ns3
 
diff --git a/model/ccnx-path-stretch-tag.h b/model/ccnx-path-stretch-tag.h
index dd49041..71a4582 100644
--- a/model/ccnx-path-stretch-tag.h
+++ b/model/ccnx-path-stretch-tag.h
@@ -34,56 +34,82 @@
 class WeightsPathStretchTag : public Tag
 {
 public:
-    WeightsPathStretchTag();
-    WeightsPathStretchTag(const WeightsPathStretchTag &o);
-    WeightsPathStretchTag &operator = (const WeightsPathStretchTag &o);
-
-    bool operator == (WeightsPathStretchTag const &o) const;
-
-    static TypeId GetTypeId(void);
-    virtual TypeId GetInstanceTypeId(void) const;
-
-    virtual uint32_t GetSerializedSize(void) const;
-    virtual void Serialize(TagBuffer i) const;
-    virtual void Deserialize(TagBuffer i);
-    virtual void Print(std::ostream &os) const;
-
-    void AddNewHop(uint32_t weight);
-    uint32_t GetValue();
+  struct NodeWeightPair
+  {
+    NodeWeightPair () : node (0), weight (0) { }
+    NodeWeightPair (Ptr<Node> _node, uint32_t _weight) : node (_node), weight (_weight) { }
     
+    Ptr<Node> node;
+    uint32_t  weight;
+  };
+  
+  static TypeId
+  GetTypeId ();
+
+  WeightsPathStretchTag ();
+  virtual ~WeightsPathStretchTag () { };
+
+  void
+  AddPathInfo (Ptr<Node> node, uint32_t weight);
+
+  uint32_t
+  GetTotalWeight () const;
+
+  Ptr<Node>
+  GetSourceNode () const;
+
+  const std::list<NodeWeightPair> &
+  GetInfos () const
+  { return m_infos; }
+
+  // from Tag
+  virtual uint32_t
+  GetSerializedSize (void) const;
+  
+  virtual void
+  Serialize (TagBuffer i) const;
+
+  virtual void
+  Deserialize (TagBuffer i);
+
+  virtual void
+  Print (std::ostream &os) const;
+  
 private:
-    uint32_t m_weightPathStretch;
+  std::list<NodeWeightPair> m_infos;
 };
 
-class DelaysPathStretchTag : public Tag
-{
-public:
-    DelaysPathStretchTag();
-    //PathSplicingPathTag(const PathSplicingPathTag &o);
-    //PathSplicingPathTag &operator = (const PathSplicingPathTag &o);
+// class DelaysPathStretchTag : public Tag
+// {
+// public:
+//   DelaysPathStretchTag();
 
-    //bool operator == (PathSplicingPathTag const &o) const;
+//   static TypeId GetTypeId(void);
+//   virtual TypeId GetInstanceTypeId(void) const;
 
-    static TypeId GetTypeId(void);
-    virtual TypeId GetInstanceTypeId(void) const;
+//   virtual uint32_t GetSerializedSize(void) const;
+//   virtual void Serialize(TagBuffer i) const;
+//   virtual void Deserialize(TagBuffer i);
+//   virtual void Print(std::ostream &os) const;
 
-    virtual uint32_t GetSerializedSize(void) const;
-    virtual void Serialize(TagBuffer i) const;
-    virtual void Deserialize(TagBuffer i);
-    virtual void Print(std::ostream &os) const;
+//   int GetNHops();
+//   void AddNewHop(double delay);
+//   int GetCurrentHop();
+//   void RemoveCurrentHop();
+//   //void RandomizeTags(UniformVariable &rand, uint32_t max);
 
-    int GetNHops();
-    void AddNewHop(double delay);
-    int GetCurrentHop();
-    void RemoveCurrentHop();
-    //void RandomizeTags(UniformVariable &rand, uint32_t max);
+// private:
+//   //PathSplicingPathTag(const PathSplicingPathTag &o);
+//   //PathSplicingPathTag &operator = (const PathSplicingPathTag &o);
 
-private:
-    std::list<double> m_delays;
-};
+//   //bool operator == (PathSplicingPathTag const &o) const;
+
+// private:
+//   std::list<double> m_delays;
+// };
 
 
 } // namespace ns3
 
 
-#endif /* PATH_STRETCH_TAG_H */
\ No newline at end of file
+#endif /* PATH_STRETCH_TAG_H */