Index: src/pgbr/model/monitor/source-destination-pairs-traffic-monitor/model/source-destination-pairs-traffic-monitor.cc |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/src/pgbr/model/monitor/source-destination-pairs-traffic-monitor/model/source-destination-pairs-traffic-monitor.cc |
@@ -0,0 +1,785 @@ |
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
+/* |
+ * Copyright (c) Waterford Institute of Technology, 2013, Julien Mineraud, BioFINT. |
+ * |
+ * This program is free software; you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 2 as |
+ * published by the Free Software Foundation; |
+ * |
+ * This program is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with this program; if not, write to the Free Software |
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
+ * |
+ * Author: Julien Mineraud <julien.mineraud@gmail.com> |
+ * |
+ * Acknowledgements: |
+ * This work has received support from Science Foundation Ireland via the |
+ * "A Biologically inspired framework supporting network management for |
+ * the Future Internet" starting investigator award (grant no. 09/SIRG/I1643). |
+ */ |
+ |
+#include "source-destination-pairs-traffic-monitor.h" |
+#include "ns3/tag.h" |
+#include "ns3/log.h" |
+#include "ns3/udp-header.h" |
+#include "ns3/tcp-header.h" |
+#include "ns3/ipv4-pgbr-protocol.h" |
+#include "ns3/aodv-routing-protocol.h" |
+#include "ns3/config.h" |
+#include "ns3/boolean.h" |
+ |
+NS_LOG_COMPONENT_DEFINE ("SourceDestinationPairsTrafficMonitor"); |
+ |
+namespace ns3 { |
+namespace pgbr { |
+ |
+TypeId |
+SourceDestinationPairsTrafficMonitorPacketTag::GetTypeId (void) |
+{ |
+ static TypeId tid = |
+ TypeId ("ns3::pgbr::SourceDestinationPairsTrafficMonitorPacketTag") |
+ .SetParent<Tag> () |
+ .AddConstructor<SourceDestinationPairsTrafficMonitorPacketTag> () |
+ ; |
+ return tid; |
+} |
+ |
+TypeId |
+SourceDestinationPairsTrafficMonitorPacketTag::GetInstanceTypeId (void) const |
+{ |
+ return GetTypeId (); |
+} |
+ |
+uint32_t |
+SourceDestinationPairsTrafficMonitorPacketTag::GetSerializedSize (void) const |
+{ |
+ // 8 for the packet id, 4 for the packet size |
+ return 8 + 4; |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitorPacketTag::Serialize (TagBuffer buf) const |
+{ |
+ buf.WriteU64 (m_packetId); |
+ buf.WriteU32 (m_packetSize); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitorPacketTag::Deserialize (TagBuffer buf) |
+{ |
+ m_packetId = buf.ReadU64 (); |
+ m_packetSize = buf.ReadU32 (); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitorPacketTag::Print (std::ostream &os) const |
+{ |
+ os << "PacketId=" << m_packetId; |
+ os << "PacketSize=" << m_packetSize; |
+} |
+ |
+SourceDestinationPairsTrafficMonitorPacketTag::SourceDestinationPairsTrafficMonitorPacketTag () |
+: Tag (), m_packetId(0), m_packetSize(0) |
+{} |
+ |
+SourceDestinationPairsTrafficMonitorPacketTag::SourceDestinationPairsTrafficMonitorPacketTag (uint64_t packetId, uint32_t packetSize) |
+: Tag (), m_packetId (packetId), m_packetSize (packetSize) |
+{} |
+ |
+void |
+SourceDestinationPairsTrafficMonitorPacketTag::SetPacketId (uint64_t id) |
+{ |
+ m_packetId = id; |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitorPacketTag::SetPacketSize (uint32_t size) |
+{ |
+ m_packetSize = size; |
+} |
+ |
+uint64_t |
+SourceDestinationPairsTrafficMonitorPacketTag::GetPacketId (void) const |
+{ |
+ return m_packetId; |
+} |
+ |
+uint32_t |
+SourceDestinationPairsTrafficMonitorPacketTag::GetPacketSize (void) const |
+{ |
+ return m_packetSize; |
+} |
+ |
+/* see http://www.iana.org/assignments/protocol-numbers */ |
+const uint8_t TCP_PROT_NUMBER = 6; |
+const uint8_t UDP_PROT_NUMBER = 17; |
+ |
+PacketClassifier::~PacketClassifier() |
+{} |
+ |
+PacketClassifier::Type |
+DefaultPacketClassifier::GetPacketClass (const Ipv4Header &header, Ptr<const Packet> packet) |
+{ |
+ /// Make sure these port number make a good classification or you may see undesired results |
+ switch (header.GetProtocol ()) |
+ { |
+ case UDP_PROT_NUMBER: |
+ { |
+ UdpHeader udpHeader; |
+ packet->PeekHeader (udpHeader); |
+ if (udpHeader.GetDestinationPort () == pgbr::Ipv4RoutingProtocol::PGBR_PORT || |
+ udpHeader.GetDestinationPort () == aodv::RoutingProtocol::AODV_PORT || //aodv |
+ udpHeader.GetDestinationPort () == 698 || //olsr |
+ udpHeader.GetDestinationPort() == 12346) //antnet |
+ { |
+ return TRACKED_ROUTING; |
+ } |
+ else |
+ { |
+ return TRACKED_DATA; |
+ } |
+ } |
+ break; |
+ |
+ case TCP_PROT_NUMBER: |
+ { |
+ TcpHeader tcpHeader; |
+ packet->PeekHeader (tcpHeader); |
+ if (tcpHeader.GetDestinationPort () == pgbr::Ipv4RoutingProtocol::PGBR_PORT || |
+ tcpHeader.GetDestinationPort () == aodv::RoutingProtocol::AODV_PORT || //aodv |
+ tcpHeader.GetDestinationPort () == 698 || //olsr |
+ tcpHeader.GetDestinationPort() == 12346) //antnet |
+ { |
+ return TRACKED_ROUTING; |
+ } |
+ else |
+ { |
+ return TRACKED_DATA; |
+ } |
+ } |
+ break; |
+ |
+ default: |
+ { |
+ return UNTRACKED; |
+ } |
+ } |
+} |
+ |
+NS_OBJECT_ENSURE_REGISTERED (SourceDestinationPairsTrafficMonitor); |
+ |
+TypeId |
+SourceDestinationPairsTrafficMonitor::GetTypeId (void) |
+{ |
+ static TypeId tid = |
+ TypeId ("ns3::pgbr::SourceDestinationPairsTrafficMonitor") |
+ .SetParent<Object> () |
+ .AddConstructor<SourceDestinationPairsTrafficMonitor> () |
+ .AddAttribute ("StartTime", ("The time when the monitoring starts."), |
+ TimeValue (Seconds (0.0)), |
+ MakeTimeAccessor (&SourceDestinationPairsTrafficMonitor::Start), |
+ MakeTimeChecker () |
+ ) |
+ .AddAttribute ("Interval", ("The interval to collect the intermediate."), |
+ TimeValue (Seconds (12.0)), |
+ MakeTimeAccessor (&SourceDestinationPairsTrafficMonitor::m_interval), |
+ MakeTimeChecker () |
+ ) |
+ .AddAttribute ("MaxDelay", |
+ "Packets still not received after this delay are to be considered lost", |
+ TimeValue (Seconds (10.0)), |
+ MakeTimeAccessor (&SourceDestinationPairsTrafficMonitor::m_maxDelay), |
+ MakeTimeChecker () |
+ ) |
+ .AddAttribute ("CheckLostPacketInterval", |
+ "IntervalToCheckForLostPackets", |
+ TimeValue (Seconds (1.0)), |
+ MakeTimeAccessor (&SourceDestinationPairsTrafficMonitor::m_checkPacketLostInterval), |
+ MakeTimeChecker () |
+ ) |
+ .AddAttribute ("LookAtSdp", |
+ "if we look at the different sdp", |
+ BooleanValue (false), |
+ MakeBooleanAccessor (&SourceDestinationPairsTrafficMonitor::m_lookAtSdp), |
+ MakeBooleanChecker () |
+ ) |
+ ; |
+ return tid; |
+} |
+ |
+TypeId |
+SourceDestinationPairsTrafficMonitor::GetInstanceTypeId (void) const |
+{ |
+ return GetTypeId (); |
+} |
+ |
+SourceDestinationPairsTrafficMonitor::SourceDestinationPairsTrafficMonitor () |
+: m_enabled (false), m_packetIdCounter (0) |
+{ |
+ m_packetClassifier = new DefaultPacketClassifier (); |
+ m_lookAtSdp = false; |
+} |
+ |
+SourceDestinationPairsTrafficMonitor::~SourceDestinationPairsTrafficMonitor () |
+{ |
+ m_intermediateStats.clear (); |
+ m_sdps.clear (); |
+ m_sdpCurrentStats.clear (); |
+ m_sdpIntermediateStats.clear (); |
+ m_destAddressMap.clear (); |
+ m_trackedPackets.clear (); |
+ if (m_packetClassifier) |
+ { |
+ delete m_packetClassifier; |
+ m_packetClassifier = 0; |
+ } |
+} |
+ |
+uint64_t |
+SourceDestinationPairsTrafficMonitor::GetNextPacketId () |
+{ |
+ return ++m_packetIdCounter; |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::ConnectToTraces () |
+{ |
+ //Connect to the first tx function |
+ Config::ConnectWithoutContext ("/NodeList/*/$ns3::Ipv4L3Protocol/SendOutgoing", |
+ MakeCallback (&SourceDestinationPairsTrafficMonitor::ReportFirstTx, Ptr<SourceDestinationPairsTrafficMonitor> (this))); |
+ |
+ //Connect to the last rx function |
+ Config::ConnectWithoutContext ("/NodeList/*/$ns3::Ipv4L3Protocol/LocalDeliver", |
+ MakeCallback (&SourceDestinationPairsTrafficMonitor::ReportLastRx, Ptr<SourceDestinationPairsTrafficMonitor> (this))); |
+ |
+ //Connect to drop function |
+ Config::ConnectWithoutContext ("/NodeList/*/$ns3::Ipv4L3Protocol/Drop", |
+ MakeCallback (&SourceDestinationPairsTrafficMonitor::ReportIpv4L3ProtocolDrop, Ptr<SourceDestinationPairsTrafficMonitor> (this))); |
+ |
+ //Connect to the queue drops of p2p devices |
+ Config::ConnectWithoutContext ("/NodeList/*/DeviceList/*/TxQueue/Drop", |
+ MakeCallback (&SourceDestinationPairsTrafficMonitor::ReportDrop, Ptr<SourceDestinationPairsTrafficMonitor> (this))); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::AddSdpToWatch (Ptr<const Node> src, Ptr<const Node> dst) |
+{ |
+ NS_ASSERT (!m_enabled); |
+ if (!m_lookAtSdp) |
+ { |
+ NS_LOG_INFO ("The monitor now recorded details for an SDP"); |
+ m_lookAtSdp = true; |
+ } |
+ |
+ sdp_t sdp = std::make_pair (src->GetId (), dst->GetId ()); |
+ if (std::find (m_sdps.begin (), m_sdps.end (), sdp) == m_sdps.end ()) |
+ { |
+ m_sdps.push_back (sdp); |
+ NS_LOG_INFO ("The monitor now recorded details for the sdp (" << src->GetId () << ", " << dst->GetId () << ")"); |
+ // For the source and the destination, map the Ipv4Address to the nodes |
+ Ptr<Ipv4> ipv4 = src->GetObject<Ipv4> (); |
+ NS_ASSERT (ipv4); |
+ for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++) |
+ { |
+ for (uint32_t j = 0; j < ipv4->GetNAddresses (i); j++) |
+ { |
+ Ipv4Address address = ipv4->GetAddress (i, j).GetLocal (); |
+ if (address != Ipv4Address ("127.0.0.1")) |
+ { |
+ m_destAddressMap[address] = src->GetId (); |
+ } |
+ } |
+ } |
+ ipv4 = dst->GetObject<Ipv4> (); |
+ NS_ASSERT (ipv4); |
+ for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++) |
+ { |
+ for (uint32_t j = 0; j < ipv4->GetNAddresses (i); j++) |
+ { |
+ Ipv4Address address = ipv4->GetAddress (i, j).GetLocal (); |
+ if (address != Ipv4Address ("127.0.0.1")) |
+ { |
+ m_destAddressMap[address] = dst->GetId (); |
+ } |
+ } |
+ } |
+ } |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::ReportFirstTx (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface) |
+{ |
+ if (!m_enabled) |
+ { |
+ return; |
+ } |
+ |
+ if (!m_packetClassifier) |
+ { |
+ NS_LOG_DEBUG ("No classifier"); |
+ return; |
+ } |
+ |
+ PacketClassifier::Type packetType = m_packetClassifier->GetPacketClass (ipHeader, ipPayload); |
+ if (packetType == PacketClassifier::UNTRACKED) |
+ { |
+ NS_LOG_LOGIC ("Packet " << ipPayload << " with ipHeader " << ipHeader << " is untracked"); |
+ return; |
+ } |
+ |
+ uint64_t packetId = GetNextPacketId (); |
+ uint32_t packetSize = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); |
+ |
+ SourceDestinationPairsTrafficMonitorPacketTag tfpTag (packetId, packetSize); |
+ ipPayload->AddPacketTag (tfpTag); |
+ |
+ Time now = Simulator::Now (); |
+ TrackedPacket &tracked = m_trackedPackets[packetId]; |
+ tracked.firstSeenTime = now; |
+ tracked.lastSeenTime = tracked.firstSeenTime; |
+ tracked.packetType = packetType; |
+ tracked.isLookedSdp = false; |
+ |
+ if (packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_currentStats.txRoutingBytes += packetSize; |
+ m_currentStats.txRoutingPackets++; |
+ } |
+ else |
+ { |
+ m_currentStats.txDataBytes += packetSize; |
+ m_currentStats.txDataPackets++; |
+ if (m_lookAtSdp) |
+ { |
+ std::map<Ipv4Address, uint32_t>::iterator srcIt = m_destAddressMap.find (ipHeader.GetSource ()); |
+ std::map<Ipv4Address, uint32_t>::iterator dstIt = m_destAddressMap.find (ipHeader.GetDestination ()); |
+ if (srcIt == m_destAddressMap.end () || dstIt == m_destAddressMap.end ()) |
+ { |
+ NS_LOG_DEBUG ("One of the address has not been found"); |
+ return; |
+ } |
+ tracked.src = srcIt->second; |
+ tracked.dst = dstIt->second; |
+ |
+ // If the sdp is monitor, add the results |
+ sdp_t sdp = std::make_pair (tracked.src, tracked.dst); |
+ if (std::find (m_sdps.begin (), m_sdps.end (), sdp) != m_sdps.end ()) |
+ { |
+ m_sdpCurrentStats[sdp].txDataBytes += packetSize; |
+ m_sdpCurrentStats[sdp].txDataPackets++; |
+ tracked.isLookedSdp = true; |
+ } |
+ } |
+ } |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::ReportLastRx (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface) |
+{ |
+ //Now the trick here is to find the m_currentStats corresponding to when the packet was issued |
+ if (!m_enabled) |
+ { |
+ return; |
+ } |
+ |
+ SourceDestinationPairsTrafficMonitorPacketTag tfpTag; |
+ // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904 |
+ if (!(ConstCast<Packet>(ipPayload)->RemovePacketTag (tfpTag))) |
+ { |
+ NS_LOG_INFO ("Packet was not tracked, discard"); |
+ return; |
+ } |
+ |
+ TrackedPacketMap::iterator tracked = m_trackedPackets.find (tfpTag.GetPacketId ()); |
+ if (tracked == m_trackedPackets.end ()) |
+ { |
+ NS_LOG_WARN ("Received packet last-tx report (packetId=" << tfpTag.GetPacketId () << ") but not known to be transmitted."); |
+ return; |
+ } |
+ |
+ Time now = Simulator::Now (); |
+ Time delay = (now - tracked->second.firstSeenTime); |
+ |
+ //Now find the |
+ if (tracked->second.firstSeenTime >= m_currentStats.startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_currentStats.rxRoutingBytes += tfpTag.GetPacketSize (); |
+ m_currentStats.rxRoutingPackets++; |
+ m_currentStats.delayRoutingSum += delay; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_currentStats.rxDataBytes += tfpTag.GetPacketSize (); |
+ m_currentStats.rxDataPackets++; |
+ m_currentStats.delayDataSum += delay; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpCurrentStats[sdp].rxDataBytes += tfpTag.GetPacketSize (); |
+ m_sdpCurrentStats[sdp].rxDataPackets++; |
+ m_sdpCurrentStats[sdp].delayDataSum += delay; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ } |
+ else |
+ { |
+ //Look for the good interval |
+ for (uint32_t i = m_intermediateStats.size () - 1; i >= 0; i++) |
+ { |
+ if (tracked->second.firstSeenTime >= m_intermediateStats[i].startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_intermediateStats[i].rxRoutingBytes += tfpTag.GetPacketSize (); |
+ m_intermediateStats[i].rxRoutingPackets++; |
+ m_intermediateStats[i].delayRoutingSum += delay; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_intermediateStats[i].rxDataBytes += tfpTag.GetPacketSize (); |
+ m_intermediateStats[i].rxDataPackets++; |
+ m_intermediateStats[i].delayDataSum += delay; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpIntermediateStats[sdp][i].rxDataBytes += tfpTag.GetPacketSize (); |
+ m_sdpIntermediateStats[sdp][i].rxDataPackets++; |
+ m_sdpIntermediateStats[sdp][i].delayDataSum += delay; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ break; |
+ } |
+ NS_LOG_ERROR ("We should never have this situation"); |
+ } |
+ } |
+ m_trackedPackets.erase (tracked); // we don't need to track this packet anymore |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::ReportIpv4L3ProtocolDrop (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, |
+ Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex) |
+{ |
+ ReportDrop (ipPayload); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::ReportDrop (Ptr<const Packet> ipPayload) |
+{ |
+ if (!m_enabled) |
+ { |
+ return; |
+ } |
+ |
+ SourceDestinationPairsTrafficMonitorPacketTag tfpTag; |
+ // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904 |
+ if (!(ConstCast<Packet>(ipPayload)->RemovePacketTag (tfpTag))) |
+ { |
+ NS_LOG_INFO ("Packet was not tracked, discard"); |
+ return; |
+ } |
+ |
+ TrackedPacketMap::iterator tracked = m_trackedPackets.find (tfpTag.GetPacketId ()); |
+ if (tracked == m_trackedPackets.end ()) |
+ { |
+ NS_LOG_WARN ("Dropped packet report (packetId=" << tfpTag.GetPacketId () << ") but not known to be transmitted."); |
+ return; |
+ } |
+ |
+ //Once a packet has been dropped we ensure, that we modify the proper interval of collection of stats |
+ if (tracked->second.firstSeenTime >= m_currentStats.startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_currentStats.lostRoutingPackets++; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_currentStats.lostDataPackets++; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpCurrentStats[sdp].lostDataPackets++; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ } |
+ else |
+ { |
+ for (uint32_t i = m_intermediateStats.size () - 1; i >= 0; i++) |
+ { |
+ if (tracked->second.firstSeenTime >= m_intermediateStats[i].startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_intermediateStats[i].lostRoutingPackets++; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_intermediateStats[i].lostDataPackets++; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpIntermediateStats[sdp][i].lostDataPackets++; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ break; |
+ } |
+ NS_LOG_ERROR ("We should never have this situation"); |
+ } |
+ } |
+ m_trackedPackets.erase (tracked); // we don't need to track this packet anymore |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::CheckForLostPackets (Time maxDelay) |
+{ |
+ Time now = Simulator::Now (); |
+ |
+ for (TrackedPacketMap::iterator tracked = m_trackedPackets.begin (); |
+ tracked != m_trackedPackets.end (); ) |
+ { |
+ if (now - tracked->second.lastSeenTime >= maxDelay) |
+ { |
+ //Once a packet has been lost we ensure, that we modify the proper interval of collection of stats |
+ if (tracked->second.firstSeenTime >= m_currentStats.startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_currentStats.lostRoutingPackets++; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_currentStats.lostDataPackets++; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpCurrentStats[sdp].lostDataPackets++; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ } |
+ else |
+ { |
+ for (uint32_t i = m_intermediateStats.size () - 1; i >= 0; i--) |
+ { |
+ if (tracked->second.firstSeenTime >= m_intermediateStats[i].startCollectionTime) |
+ { |
+ if (tracked->second.packetType == PacketClassifier::TRACKED_ROUTING) |
+ { |
+ m_intermediateStats[i].lostRoutingPackets++; |
+ } |
+ else if (tracked->second.packetType == PacketClassifier::TRACKED_DATA) |
+ { |
+ m_intermediateStats[i].lostDataPackets++; |
+ if (m_lookAtSdp && tracked->second.isLookedSdp) |
+ { |
+ sdp_t sdp = std::make_pair (tracked->second.src, tracked->second.dst); |
+ m_sdpIntermediateStats[sdp][i].lostDataPackets++; |
+ } |
+ } |
+ else |
+ { |
+ NS_LOG_ERROR ("We should not have found an untracked packet"); |
+ } |
+ break; |
+ } |
+ NS_LOG_ERROR ("We should never have this situation"); |
+ } |
+ } |
+ // we won't track it anymore |
+ m_trackedPackets.erase (tracked++); |
+ } |
+ else |
+ { |
+ ++tracked; |
+ } |
+ } |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::PeriodicCheckForLostPackets () |
+{ |
+ CheckForLostPackets (m_maxDelay); |
+ Simulator::Schedule (m_checkPacketLostInterval, &SourceDestinationPairsTrafficMonitor::PeriodicCheckForLostPackets, this); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::NotifyConstructionCompleted () |
+{ |
+ Object::NotifyConstructionCompleted (); |
+ Simulator::Schedule (m_checkPacketLostInterval, &SourceDestinationPairsTrafficMonitor::PeriodicCheckForLostPackets, this); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::Start (const Time &time) |
+{ |
+ if (m_enabled) |
+ { |
+ return; |
+ } |
+ Simulator::Cancel (m_startEvent); |
+ |
+ m_startEvent = Simulator::Schedule (time, &SourceDestinationPairsTrafficMonitor::StartRightNow, Ptr<SourceDestinationPairsTrafficMonitor> (this)); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::Stop (const Time &time) |
+{ |
+ if (!m_enabled) |
+ { |
+ return; |
+ } |
+ Simulator::Cancel (m_stopEvent); |
+ m_stopEvent = Simulator::Schedule (time, &SourceDestinationPairsTrafficMonitor::StopRightNow, Ptr<SourceDestinationPairsTrafficMonitor> (this)); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::StartRightNow () |
+{ |
+ if (m_enabled) |
+ { |
+ return; |
+ } |
+ |
+ if (m_lookAtSdp) |
+ { |
+ for (std::vector<sdp_t>::iterator it = m_sdps.begin (); it != m_sdps.end (); it++) |
+ { |
+ IntermediateStats stats; |
+ m_sdpCurrentStats[*it] = stats; |
+ } |
+ } |
+ |
+ ConnectToTraces (); |
+ m_enabled = true; |
+ |
+ Simulator::Schedule (m_interval, &SourceDestinationPairsTrafficMonitor::CollectIntermediateStats, Ptr<SourceDestinationPairsTrafficMonitor> (this)); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::StopRightNow () |
+{ |
+ if (!m_enabled) |
+ { |
+ return; |
+ } |
+ m_enabled = false; |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::CollectIntermediateStats (void) |
+{ |
+ m_currentStats.stopCollectionTime = Simulator::Now (); |
+ if (m_currentStats.startCollectionTime != m_currentStats.stopCollectionTime) |
+ { |
+ m_intermediateStats.push_back (m_currentStats); |
+ } |
+ IntermediateStats newStats; |
+ newStats.startCollectionTime = Simulator::Now (); |
+ m_currentStats = newStats; |
+ |
+ if (m_lookAtSdp) |
+ { |
+ for (std::vector<sdp_t>::iterator it = m_sdps.begin (); it != m_sdps.end (); it++) |
+ { |
+ m_sdpCurrentStats[*it].stopCollectionTime = Simulator::Now (); |
+ if (m_sdpCurrentStats[*it].startCollectionTime != m_sdpCurrentStats[*it].stopCollectionTime) |
+ { |
+ m_sdpIntermediateStats[*it].push_back (m_sdpCurrentStats[*it]); |
+ } |
+ IntermediateStats newSdpStats; |
+ newSdpStats.startCollectionTime = Simulator::Now (); |
+ m_sdpCurrentStats[*it] = newSdpStats; |
+ } |
+ } |
+ |
+ Simulator::Schedule (m_interval, &SourceDestinationPairsTrafficMonitor::CollectIntermediateStats, Ptr<SourceDestinationPairsTrafficMonitor> (this)); |
+} |
+ |
+void |
+SourceDestinationPairsTrafficMonitor::SerializeToStream (Ptr<OutputStreamWrapper> stream, bool serializeSdp) |
+{ |
+ |
+ if (!stream) |
+ { |
+ NS_FATAL_ERROR ("No stream provided"); |
+ return; |
+ } |
+ |
+ CollectIntermediateStats (); |
+ |
+ // We serialize to an ASCII format to ease the post-processing of data |
+ if (!serializeSdp) |
+ { |
+ uint32_t id = 1; |
+ for (std::deque<IntermediateStats>::iterator iter = m_intermediateStats.begin (); iter != m_intermediateStats.end (); iter++, id++) |
+ { |
+ *(stream)->GetStream() << id << "\t" << |
+ iter->startCollectionTime .GetSeconds () << "\t" << iter->stopCollectionTime.GetSeconds () << "\t" << |
+ iter->txDataPackets << "\t" << iter->rxDataPackets << "\t" << |
+ iter->txDataBytes << "\t" << iter->rxDataBytes << "\t" << |
+ iter->lostDataPackets << "\t" << iter->delayDataSum.GetSeconds() << "\t" << |
+ iter->txRoutingPackets << "\t" << iter->rxRoutingPackets << "\t" << |
+ iter->txRoutingBytes << "\t" << iter->rxRoutingBytes << "\t" << |
+ iter->lostRoutingPackets << "\t" << iter->delayRoutingSum.GetSeconds() << std::endl; |
+ } |
+ } |
+ else |
+ { |
+ for (std::vector<sdp_t>::iterator it = m_sdps.begin (); it != m_sdps.end (); it++) |
+ { |
+ uint32_t id = 1; |
+ for (std::deque<IntermediateStats>::iterator iter = m_sdpIntermediateStats[*it].begin (); iter != m_sdpIntermediateStats[*it].end (); iter++, id++) |
+ { |
+ *(stream)->GetStream() << id << "\t" << (*it).first << "\t" << (*it).second << "\t" << |
+ iter->startCollectionTime .GetSeconds () << "\t" << iter->stopCollectionTime.GetSeconds () << "\t" << |
+ iter->txDataPackets << "\t" << iter->rxDataPackets << "\t" << |
+ iter->txDataBytes << "\t" << iter->rxDataBytes << "\t" << |
+ iter->lostDataPackets << "\t" << iter->delayDataSum.GetSeconds() << "\t" << |
+ iter->txRoutingPackets << "\t" << iter->rxRoutingPackets << "\t" << |
+ iter->txRoutingBytes << "\t" << iter->rxRoutingBytes << "\t" << |
+ iter->lostRoutingPackets << "\t" << iter->delayRoutingSum.GetSeconds() << std::endl; |
+ |
+ } |
+ } |
+ uint32_t id = 1; |
+ for (std::deque<IntermediateStats>::iterator iter = m_intermediateStats.begin (); iter != m_intermediateStats.end (); iter++, id++) |
+ { |
+ *(stream)->GetStream() << id << "\t-1\t-1\t" << |
+ iter->startCollectionTime .GetSeconds () << "\t" << iter->stopCollectionTime.GetSeconds () << "\t" << |
+ iter->txDataPackets << "\t" << iter->rxDataPackets << "\t" << |
+ iter->txDataBytes << "\t" << iter->rxDataBytes << "\t" << |
+ iter->lostDataPackets << "\t" << iter->delayDataSum.GetSeconds() << "\t" << |
+ iter->txRoutingPackets << "\t" << iter->rxRoutingPackets << "\t" << |
+ iter->txRoutingBytes << "\t" << iter->rxRoutingBytes << "\t" << |
+ iter->lostRoutingPackets << "\t" << iter->delayRoutingSum.GetSeconds() << std::endl; |
+ } |
+ } |
+} |
+ |
+}} // namespace pgbr, ns3 |