Bug 854 - Support DROP_QUEUE reason-code in Ipv4FlowProbe
authorWilson Thong <wilsonwk@ee.cityu.edu.hk>
Mon, 31 May 2010 13:32:24 +0100
changeset 6323 2a8ec4aee3b5
parent 6322 d36455b47a34
child 6324 e56ec0532fec
Bug 854 - Support DROP_QUEUE reason-code in Ipv4FlowProbe
src/contrib/flow-monitor/ipv4-flow-probe.cc
src/contrib/flow-monitor/ipv4-flow-probe.h
--- a/src/contrib/flow-monitor/ipv4-flow-probe.cc	Sun May 30 20:54:25 2010 -0700
+++ b/src/contrib/flow-monitor/ipv4-flow-probe.cc	Mon May 31 13:32:24 2010 +0100
@@ -25,16 +25,125 @@
 #include "ns3/flow-monitor.h"
 #include "ns3/log.h"
 #include "ns3/pointer.h"
+#include "ns3/config.h"
+#include "ns3/flow-id-tag.h"
 
 namespace ns3 {
 
+using namespace std;
+
 NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe");
+
+            //////////////////////////////////////
+            // Ipv4FlowProbeTag class implementation //
+            //////////////////////////////////////
+
+class Ipv4FlowProbeTag : public Tag
+{
+public:
+  static TypeId GetTypeId (void);
+  virtual TypeId GetInstanceTypeId (void) const;
+  virtual uint32_t GetSerializedSize (void) const;
+  virtual void Serialize (TagBuffer buf) const;
+  virtual void Deserialize (TagBuffer buf);
+  virtual void Print (std::ostream &os) const;
+  Ipv4FlowProbeTag ();
+  Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize);
+  void SetFlowId (uint32_t flowId);
+  void SetPacketId (uint32_t packetId);
+  void SetPacketSize (uint32_t packetSize);
+  uint32_t GetFlowId (void) const;
+  uint32_t GetPacketId (void) const;
+  uint32_t GetPacketSize (void) const;
+private:
+  uint32_t m_flowId;
+  uint32_t m_packetId;
+  uint32_t m_packetSize;
   
+};
 
-Ipv4FlowProbe::~Ipv4FlowProbe ()
+TypeId 
+Ipv4FlowProbeTag::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
+    .SetParent<Tag> ()
+    .AddConstructor<Ipv4FlowProbeTag> ()
+    ;
+  return tid;
+}
+TypeId 
+Ipv4FlowProbeTag::GetInstanceTypeId (void) const
+{
+  return GetTypeId ();
+}
+uint32_t 
+Ipv4FlowProbeTag::GetSerializedSize (void) const
+{
+  return 4 + 4 + 4;
+}
+void 
+Ipv4FlowProbeTag::Serialize (TagBuffer buf) const
+{
+  buf.WriteU32 (m_flowId);
+  buf.WriteU32 (m_packetId);
+  buf.WriteU32 (m_packetSize);
+}
+void 
+Ipv4FlowProbeTag::Deserialize (TagBuffer buf)
+{
+  m_flowId = buf.ReadU32 ();
+  m_packetId = buf.ReadU32 ();
+  m_packetSize = buf.ReadU32 ();
+}
+void 
+Ipv4FlowProbeTag::Print (std::ostream &os) const
 {
+  os << "FlowId=" << m_flowId;
+  os << "PacketId=" << m_packetId;
+  os << "PacketSize=" << m_packetSize;
 }
-  
+Ipv4FlowProbeTag::Ipv4FlowProbeTag ()
+  : Tag () 
+{}
+
+Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize)
+  : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize)
+{}
+
+void
+Ipv4FlowProbeTag::SetFlowId (uint32_t id)
+{
+  m_flowId = id;
+}
+void
+Ipv4FlowProbeTag::SetPacketId (uint32_t id)
+{
+  m_packetId = id;
+}
+void
+Ipv4FlowProbeTag::SetPacketSize (uint32_t size)
+{
+  m_packetSize = size;
+}
+uint32_t
+Ipv4FlowProbeTag::GetFlowId (void) const
+{
+  return m_flowId;
+}  
+uint32_t
+Ipv4FlowProbeTag::GetPacketId (void) const
+{
+  return m_packetId;
+} 
+uint32_t
+Ipv4FlowProbeTag::GetPacketSize (void) const
+{
+  return m_packetSize;
+} 
+
+            ////////////////////////////////////////
+            // Ipv4FlowProbe class implementation //
+            ////////////////////////////////////////
 
 Ipv4FlowProbe::Ipv4FlowProbe (Ptr<FlowMonitor> monitor,
                               Ptr<Ipv4FlowClassifier> classifier,
@@ -67,6 +176,11 @@
     {
       NS_FATAL_ERROR ("trace fail");
     }
+
+  // code copied from point-to-point-helper.cc
+  std::ostringstream oss;
+  oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
+  Config::ConnectWithoutContext (oss.str (), MakeCallback (&Ipv4FlowProbe::QueueDropLogger, Ptr<Ipv4FlowProbe> (this)));
 }
 
 void
@@ -81,6 +195,11 @@
       NS_LOG_DEBUG ("ReportFirstTx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
                     << ipHeader << *ipPayload);
       m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
+
+      // tag the packet with the flow id and packet id, so that the packet can be identified even
+      // when Ipv4Header is not accessible at some non-IPv4 protocol layer
+      Ipv4FlowProbeTag fTag (flowId, packetId, size);
+      ipPayload->AddPacketTag (fTag);
     }
 }
 
@@ -107,6 +226,13 @@
   
   if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
     {
+      // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+      Ipv4FlowProbeTag fTag;
+
+      // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+      bool tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+      NS_ASSERT_MSG (tagFound, "Ipv4FlowProbeTag is missing");
+
       uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
       NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
       m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
@@ -140,9 +266,16 @@
 
   if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
     {
+      // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+      Ipv4FlowProbeTag fTag;
+
+      // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+      bool tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+      NS_ASSERT_MSG (tagFound, "Ipv4FlowProbeTag is missing");
+
       uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
-      NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
-                    << ", destIp=" << ipHeader.GetDestination () << "); "
+      NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason 
+                    << ", destIp=" << ipHeader.GetDestination () << "); " 
                     << "HDR: " << ipHeader << " PKT: " << *ipPayload);
 
       DropReason myReason;
@@ -171,7 +304,25 @@
     }
 }
 
+void 
+Ipv4FlowProbe::QueueDropLogger (Ptr<const Packet> ipPayload)
+{
+  // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+  Ipv4FlowProbeTag fTag;
 
+  // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+  bool tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+  NS_ASSERT_MSG (tagFound, "FlowProbeTag is missing");
+  
+  FlowId flowId = fTag.GetFlowId ();
+  FlowPacketId packetId = fTag.GetPacketId ();
+  uint32_t size = fTag.GetPacketSize ();
+
+  NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE 
+                << "); ");
+
+  m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
+}
 
 } // namespace ns3
 
--- a/src/contrib/flow-monitor/ipv4-flow-probe.h	Sun May 30 20:54:25 2010 -0700
+++ b/src/contrib/flow-monitor/ipv4-flow-probe.h	Mon May 31 13:32:24 2010 +0100
@@ -48,12 +48,19 @@
     {
       /// Packet dropped due to missing route to the destination
       DROP_NO_ROUTE = 0,
+
       /// Packet dropped due to TTL decremented to zero during IPv4 forwarding
       DROP_TTL_EXPIRE,      
+
       /// Packet dropped due to invalid checksum in the IPv4 header
       DROP_BAD_CHECKSUM,
 
-      // DROP_QUEUE, // TODO: this is not easy to do
+      /// Packet dropped due to queue overflow.  Note: only works for
+      /// NetDevices that provide a TxQueue attribute of type Queue
+      /// with a Drop trace source.  It currently works with Csma and
+      /// PointToPoint devices, but not with WiFi or WiMax.
+      DROP_QUEUE,
+      
       DROP_INVALID_REASON,
     };
 
@@ -64,6 +71,7 @@
   void ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
   void DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
                    Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex);
+  void QueueDropLogger (Ptr<const Packet> ipPayload);
 
   Ptr<Ipv4FlowClassifier> m_classifier;
 };