--- a/CHANGES.html Wed Mar 08 18:02:07 2017 +0100
+++ b/CHANGES.html Wed Mar 08 18:02:10 2017 +0100
@@ -86,6 +86,10 @@
optional and if not specified defaults to the previous behavior (Time::S).
</li>
<li><b>TxopTrace</b>: new trace source exported by EdcaTxopN.</li>
+<li>A <b>GetDscpCounts</b> method is added to <b>Ipv4FlowClassifier</b> and <b>Ipv6FlowClassifier</b>
+ 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.
+</li>
</ul>
<h2>Changes to existing API:</h2>
<ul>
--- a/examples/traffic-control/traffic-control.cc Wed Mar 08 18:02:07 2017 +0100
+++ b/examples/traffic-control/traffic-control.cc Wed Mar 08 18:02:10 2017 +0100
@@ -153,7 +153,9 @@
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 @@
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<uint32_t>(p.first) << std::dec
+ << " count: "<< p.second << std::endl;
+ }
Simulator::Destroy ();
--- a/src/flow-monitor/model/ipv4-flow-classifier.cc Wed Mar 08 18:02:07 2017 +0100
+++ b/src/flow-monitor/model/ipv4-flow-classifier.cc Wed Mar 08 18:02:10 2017 +0100
@@ -23,6 +23,7 @@
#include "ipv4-flow-classifier.h"
#include "ns3/udp-header.h"
#include "ns3/tcp-header.h"
+#include <algorithm>
namespace ns3 {
@@ -156,12 +157,24 @@
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<std::map<Ipv4Header::DscpType, uint32_t>::iterator, bool> dscpInserter
+ = m_flowDscpMap[insert.first->second].insert (std::pair<Ipv4Header::DscpType, uint32_t> (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 @@
return retval;
}
+bool
+Ipv4FlowClassifier::SortByCount::operator() (std::pair<Ipv4Header::DscpType, uint32_t> left,
+ std::pair<Ipv4Header::DscpType, uint32_t> right)
+{
+ return left.second > right.second;
+}
+
+std::vector<std::pair<Ipv4Header::DscpType, uint32_t> >
+Ipv4FlowClassifier::GetDscpCounts (FlowId flowId) const
+{
+ std::map<FlowId, std::map<Ipv4Header::DscpType, uint32_t> >::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<std::pair<Ipv4Header::DscpType, uint32_t> > 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 @@
<< " 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<FlowId, std::map<Ipv4Header::DscpType, uint32_t> >::const_iterator flow
+ = m_flowDscpMap.find (iter->second);
+
+ if (flow != m_flowDscpMap.end ())
+ {
+ for (std::map<Ipv4Header::DscpType, uint32_t>::const_iterator i = flow->second.begin (); i != flow->second.end (); i++)
+ {
+ Indent (os, indent);
+ os << "<Dscp value=\"0x" << std::hex << static_cast<uint32_t> (i->first) << "\""
+ << " packets=\"" << std::dec << i->second << "\" />\n";
+ }
+ }
+
+ indent -= 2;
+ Indent (os, indent); os << "</Flow>\n";
}
indent -= 2;
--- a/src/flow-monitor/model/ipv4-flow-classifier.h Wed Mar 08 18:02:07 2017 +0100
+++ b/src/flow-monitor/model/ipv4-flow-classifier.h Wed Mar 08 18:02:10 2017 +0100
@@ -69,6 +69,21 @@
/// \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<Ipv4Header::DscpType, uint32_t> left,
+ std::pair<Ipv4Header::DscpType, uint32_t> 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<std::pair<Ipv4Header::DscpType, uint32_t> > GetDscpCounts (FlowId flowId) const;
+
virtual void SerializeToXmlStream (std::ostream &os, uint16_t indent) const;
private:
@@ -77,6 +92,8 @@
std::map<FiveTuple, FlowId> m_flowMap;
/// Map to FlowIds to FlowPacketId
std::map<FlowId, FlowPacketId> m_flowPktIdMap;
+ /// Map FlowIds to (DSCP value, packet count) pairs
+ std::map<FlowId, std::map<Ipv4Header::DscpType, uint32_t> > m_flowDscpMap;
};
--- a/src/flow-monitor/model/ipv6-flow-classifier.cc Wed Mar 08 18:02:07 2017 +0100
+++ b/src/flow-monitor/model/ipv6-flow-classifier.cc Wed Mar 08 18:02:10 2017 +0100
@@ -24,6 +24,7 @@
#include "ipv6-flow-classifier.h"
#include "ns3/udp-header.h"
#include "ns3/tcp-header.h"
+#include <algorithm>
namespace ns3 {
@@ -157,12 +158,24 @@
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<std::map<Ipv6Header::DscpType, uint32_t>::iterator, bool> dscpInserter
+ = m_flowDscpMap[insert.first->second].insert (std::pair<Ipv6Header::DscpType, uint32_t> (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 @@
return retval;
}
+bool
+Ipv6FlowClassifier::SortByCount::operator() (std::pair<Ipv6Header::DscpType, uint32_t> left,
+ std::pair<Ipv6Header::DscpType, uint32_t> right)
+{
+ return left.second > right.second;
+}
+
+std::vector<std::pair<Ipv6Header::DscpType, uint32_t> >
+Ipv6FlowClassifier::GetDscpCounts (FlowId flowId) const
+{
+ std::map<FlowId, std::map<Ipv6Header::DscpType, uint32_t> >::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<std::pair<Ipv6Header::DscpType, uint32_t> > 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 @@
<< " 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<FlowId, std::map<Ipv6Header::DscpType, uint32_t> >::const_iterator flow
+ = m_flowDscpMap.find (iter->second);
+
+ if (flow != m_flowDscpMap.end ())
+ {
+ for (std::map<Ipv6Header::DscpType, uint32_t>::const_iterator i = flow->second.begin (); i != flow->second.end (); i++)
+ {
+ Indent (os, indent);
+ os << "<Dscp value=\"0x" << std::hex << static_cast<uint32_t> (i->first) << "\""
+ << " packets=\"" << std::dec << i->second << "\" />\n";
+ }
+ }
+
+ indent -= 2;
+ Indent (os, indent); os << "</Flow>\n";
}
indent -= 2;
--- a/src/flow-monitor/model/ipv6-flow-classifier.h Wed Mar 08 18:02:07 2017 +0100
+++ b/src/flow-monitor/model/ipv6-flow-classifier.h Wed Mar 08 18:02:10 2017 +0100
@@ -70,6 +70,21 @@
/// \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<Ipv6Header::DscpType, uint32_t> left,
+ std::pair<Ipv6Header::DscpType, uint32_t> 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<std::pair<Ipv6Header::DscpType, uint32_t> > GetDscpCounts (FlowId flowId) const;
+
virtual void SerializeToXmlStream (std::ostream &os, uint16_t indent) const;
private:
@@ -78,6 +93,8 @@
std::map<FiveTuple, FlowId> m_flowMap;
/// Map to FlowIds to FlowPacketId
std::map<FlowId, FlowPacketId> m_flowPktIdMap;
+ /// Map FlowIds to (DSCP value, packet count) pairs
+ std::map<FlowId, std::map<Ipv6Header::DscpType, uint32_t> > m_flowDscpMap;
};