From 11bdd2e3c8e5f385e02fe7378ebfcbb08f13c218 Mon Sep 17 00:00:00 2001
From: Stefano Avallone
Date: Wed, 8 Mar 2017 18:02:10 +0100
Subject: [PATCH] flow-monitor: Keep track of the DSCP value of packets
---
CHANGES.html | 4 ++
examples/traffic-control/traffic-control.cc | 10 +++-
.../model/ipv4-flow-classifier.cc | 56 ++++++++++++++++++-
src/flow-monitor/model/ipv4-flow-classifier.h | 17 ++++++
.../model/ipv6-flow-classifier.cc | 56 ++++++++++++++++++-
src/flow-monitor/model/ipv6-flow-classifier.h | 17 ++++++
6 files changed, 155 insertions(+), 5 deletions(-)
diff --git a/CHANGES.html b/CHANGES.html
index ea6f7f92b..d2af31c2e 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -86,6 +86,10 @@ us a note on ns-developers mailing list.
optional and if not specified defaults to the previous behavior (Time::S).
TxopTrace: new trace source exported by EdcaTxopN.
+A GetDscpCounts method is added to Ipv4FlowClassifier and Ipv6FlowClassifier
+ which returns a vector of pairs (dscp,count), each of which indicates how many packets with the
+ associated dscp value have been classified for a given flow.
+
Changes to existing API:
diff --git a/examples/traffic-control/traffic-control.cc b/examples/traffic-control/traffic-control.cc
index 0bdbc3bd1..95e2ced0c 100644
--- a/examples/traffic-control/traffic-control.cc
+++ b/examples/traffic-control/traffic-control.cc
@@ -153,7 +153,9 @@ main (int argc, char *argv[])
onoff.SetAttribute ("DataRate", StringValue ("50Mbps")); //bit/s
ApplicationContainer apps;
- AddressValue remoteAddress (InetSocketAddress (interfaces.GetAddress (0), port));
+ InetSocketAddress rmt (interfaces.GetAddress (0), port);
+ rmt.SetTos (0xb8);
+ AddressValue remoteAddress (rmt);
onoff.SetAttribute ("Remote", remoteAddress);
apps.Add (onoff.Install (nodes.Get (1)));
apps.Start (Seconds (1.0));
@@ -194,6 +196,12 @@ main (int argc, char *argv[])
std::cout << " Throughput: " << stats[1].rxBytes * 8.0 / (stats[1].timeLastRxPacket.GetSeconds () - stats[1].timeFirstRxPacket.GetSeconds ()) / 1000000 << " Mbps" << std::endl;
std::cout << " Mean delay: " << stats[1].delaySum.GetSeconds () / stats[1].rxPackets << std::endl;
std::cout << " Mean jitter: " << stats[1].jitterSum.GetSeconds () / (stats[1].rxPackets - 1) << std::endl;
+ auto dscpVec = classifier->GetDscpCounts (1);
+ for (auto p : dscpVec)
+ {
+ std::cout << " DSCP value: 0x" << std::hex << static_cast(p.first) << std::dec
+ << " count: "<< p.second << std::endl;
+ }
Simulator::Destroy ();
diff --git a/src/flow-monitor/model/ipv4-flow-classifier.cc b/src/flow-monitor/model/ipv4-flow-classifier.cc
index ac9671fc6..6a103f9ee 100644
--- a/src/flow-monitor/model/ipv4-flow-classifier.cc
+++ b/src/flow-monitor/model/ipv4-flow-classifier.cc
@@ -23,6 +23,7 @@
#include "ipv4-flow-classifier.h"
#include "ns3/udp-header.h"
#include "ns3/tcp-header.h"
+#include
namespace ns3 {
@@ -156,12 +157,24 @@ Ipv4FlowClassifier::Classify (const Ipv4Header &ipHeader, Ptr ipPa
FlowId newFlowId = GetNewFlowId ();
insert.first->second = newFlowId;
m_flowPktIdMap[newFlowId] = 0;
+ m_flowDscpMap[newFlowId];
}
else
{
m_flowPktIdMap[insert.first->second] ++;
}
+ // increment the counter of packets with the same DSCP value
+ Ipv4Header::DscpType dscp = ipHeader.GetDscp ();
+ std::pair::iterator, bool> dscpInserter
+ = m_flowDscpMap[insert.first->second].insert (std::pair (dscp, 1));
+
+ // if the insertion did not succeed, we need to increment the counter
+ if (!dscpInserter.second)
+ {
+ m_flowDscpMap[insert.first->second][dscp] ++;
+ }
+
*out_flowId = insert.first->second;
*out_packetId = m_flowPktIdMap[*out_flowId];
@@ -185,6 +198,29 @@ Ipv4FlowClassifier::FindFlow (FlowId flowId) const
return retval;
}
+bool
+Ipv4FlowClassifier::SortByCount::operator() (std::pair left,
+ std::pair right)
+{
+ return left.second > right.second;
+}
+
+std::vector >
+Ipv4FlowClassifier::GetDscpCounts (FlowId flowId) const
+{
+ std::map >::const_iterator flow
+ = m_flowDscpMap.find (flowId);
+
+ if (flow == m_flowDscpMap.end ())
+ {
+ NS_FATAL_ERROR ("Could not find the flow with ID " << flowId);
+ }
+
+ std::vector > v (flow->second.begin (), flow->second.end ());
+ std::sort (v.begin (), v.end (), SortByCount ());
+ return v;
+}
+
void
Ipv4FlowClassifier::SerializeToXmlStream (std::ostream &os, uint16_t indent) const
{
@@ -200,8 +236,24 @@ Ipv4FlowClassifier::SerializeToXmlStream (std::ostream &os, uint16_t indent) con
<< " destinationAddress=\"" << iter->first.destinationAddress << "\""
<< " protocol=\"" << int(iter->first.protocol) << "\""
<< " sourcePort=\"" << iter->first.sourcePort << "\""
- << " destinationPort=\"" << iter->first.destinationPort << "\""
- << " />\n";
+ << " destinationPort=\"" << iter->first.destinationPort << "\">\n";
+
+ indent += 2;
+ std::map >::const_iterator flow
+ = m_flowDscpMap.find (iter->second);
+
+ if (flow != m_flowDscpMap.end ())
+ {
+ for (std::map::const_iterator i = flow->second.begin (); i != flow->second.end (); i++)
+ {
+ Indent (os, indent);
+ os << " (i->first) << "\""
+ << " packets=\"" << std::dec << i->second << "\" />\n";
+ }
+ }
+
+ indent -= 2;
+ Indent (os, indent); os << "\n";
}
indent -= 2;
diff --git a/src/flow-monitor/model/ipv4-flow-classifier.h b/src/flow-monitor/model/ipv4-flow-classifier.h
index 49aadbd54..ada9542d1 100644
--- a/src/flow-monitor/model/ipv4-flow-classifier.h
+++ b/src/flow-monitor/model/ipv4-flow-classifier.h
@@ -69,6 +69,21 @@ public:
/// \returns the FiveTuple corresponding to flowId
FiveTuple FindFlow (FlowId flowId) const;
+ /// Comparator used to sort the vector of DSCP values
+ class SortByCount
+ {
+ public:
+ bool operator() (std::pair left,
+ std::pair right);
+ };
+
+ /// \brief get the DSCP values of the packets belonging to the flow with the
+ /// given FlowId, sorted in decreasing order of number of packets seen with
+ /// that DSCP value
+ /// \param flowId the identifier of the flow of interest
+ /// \returns the vector of DSCP values
+ std::vector > GetDscpCounts (FlowId flowId) const;
+
virtual void SerializeToXmlStream (std::ostream &os, uint16_t indent) const;
private:
@@ -77,6 +92,8 @@ private:
std::map m_flowMap;
/// Map to FlowIds to FlowPacketId
std::map m_flowPktIdMap;
+ /// Map FlowIds to (DSCP value, packet count) pairs
+ std::map > m_flowDscpMap;
};
diff --git a/src/flow-monitor/model/ipv6-flow-classifier.cc b/src/flow-monitor/model/ipv6-flow-classifier.cc
index 5d09b227c..6f29debce 100644
--- a/src/flow-monitor/model/ipv6-flow-classifier.cc
+++ b/src/flow-monitor/model/ipv6-flow-classifier.cc
@@ -24,6 +24,7 @@
#include "ipv6-flow-classifier.h"
#include "ns3/udp-header.h"
#include "ns3/tcp-header.h"
+#include
namespace ns3 {
@@ -157,12 +158,24 @@ Ipv6FlowClassifier::Classify (const Ipv6Header &ipHeader, Ptr ipPa
FlowId newFlowId = GetNewFlowId ();
insert.first->second = newFlowId;
m_flowPktIdMap[newFlowId] = 0;
+ m_flowDscpMap[newFlowId];
}
else
{
m_flowPktIdMap[insert.first->second] ++;
}
+ // increment the counter of packets with the same DSCP value
+ Ipv6Header::DscpType dscp = ipHeader.GetDscp ();
+ std::pair::iterator, bool> dscpInserter
+ = m_flowDscpMap[insert.first->second].insert (std::pair (dscp, 1));
+
+ // if the insertion did not succeed, we need to increment the counter
+ if (!dscpInserter.second)
+ {
+ m_flowDscpMap[insert.first->second][dscp] ++;
+ }
+
*out_flowId = insert.first->second;
*out_packetId = m_flowPktIdMap[*out_flowId];
@@ -186,6 +199,29 @@ Ipv6FlowClassifier::FindFlow (FlowId flowId) const
return retval;
}
+bool
+Ipv6FlowClassifier::SortByCount::operator() (std::pair left,
+ std::pair right)
+{
+ return left.second > right.second;
+}
+
+std::vector >
+Ipv6FlowClassifier::GetDscpCounts (FlowId flowId) const
+{
+ std::map >::const_iterator flow
+ = m_flowDscpMap.find (flowId);
+
+ if (flow == m_flowDscpMap.end ())
+ {
+ NS_FATAL_ERROR ("Could not find the flow with ID " << flowId);
+ }
+
+ std::vector > v (flow->second.begin (), flow->second.end ());
+ std::sort (v.begin (), v.end (), SortByCount ());
+ return v;
+}
+
void
Ipv6FlowClassifier::SerializeToXmlStream (std::ostream &os, uint16_t indent) const
{
@@ -201,8 +237,24 @@ Ipv6FlowClassifier::SerializeToXmlStream (std::ostream &os, uint16_t indent) con
<< " destinationAddress=\"" << iter->first.destinationAddress << "\""
<< " protocol=\"" << int(iter->first.protocol) << "\""
<< " sourcePort=\"" << iter->first.sourcePort << "\""
- << " destinationPort=\"" << iter->first.destinationPort << "\""
- << " />\n";
+ << " destinationPort=\"" << iter->first.destinationPort << "\">\n";
+
+ indent += 2;
+ std::map >::const_iterator flow
+ = m_flowDscpMap.find (iter->second);
+
+ if (flow != m_flowDscpMap.end ())
+ {
+ for (std::map::const_iterator i = flow->second.begin (); i != flow->second.end (); i++)
+ {
+ Indent (os, indent);
+ os << " (i->first) << "\""
+ << " packets=\"" << std::dec << i->second << "\" />\n";
+ }
+ }
+
+ indent -= 2;
+ Indent (os, indent); os << "\n";
}
indent -= 2;
diff --git a/src/flow-monitor/model/ipv6-flow-classifier.h b/src/flow-monitor/model/ipv6-flow-classifier.h
index bd0b9faec..658c9006b 100644
--- a/src/flow-monitor/model/ipv6-flow-classifier.h
+++ b/src/flow-monitor/model/ipv6-flow-classifier.h
@@ -70,6 +70,21 @@ public:
/// \returns the FiveTuple corresponding to flowId
FiveTuple FindFlow (FlowId flowId) const;
+ /// Comparator used to sort the vector of DSCP values
+ class SortByCount
+ {
+ public:
+ bool operator() (std::pair left,
+ std::pair right);
+ };
+
+ /// \brief get the DSCP values of the packets belonging to the flow with the
+ /// given FlowId, sorted in decreasing order of number of packets seen with
+ /// that DSCP value
+ /// \param flowId the identifier of the flow of interest
+ /// \returns the vector of DSCP values
+ std::vector > GetDscpCounts (FlowId flowId) const;
+
virtual void SerializeToXmlStream (std::ostream &os, uint16_t indent) const;
private:
@@ -78,6 +93,8 @@ private:
std::map m_flowMap;
/// Map to FlowIds to FlowPacketId
std::map m_flowPktIdMap;
+ /// Map FlowIds to (DSCP value, packet count) pairs
+ std::map > m_flowDscpMap;
};