From 623726eeb0e62040b47cb6d54e9480e473b3c907 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 31 Aug 2009 18:48:37 +0100 Subject: [PATCH 1/8] Ipv4L3Protocol::Drop trace source enhanced, and add new SendOutgoing, UnicastForward, and LocalDeliver trace sources, for the FlowMonitor. --- src/internet-stack/ipv4-l3-protocol.cc | 51 ++++++++++++++++++-------- src/internet-stack/ipv4-l3-protocol.h | 17 ++++++++- 2 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/internet-stack/ipv4-l3-protocol.cc b/src/internet-stack/ipv4-l3-protocol.cc index 793b8bb43..b3539248d 100644 --- a/src/internet-stack/ipv4-l3-protocol.cc +++ b/src/internet-stack/ipv4-l3-protocol.cc @@ -69,6 +69,14 @@ Ipv4L3Protocol::GetTypeId (void) ObjectVectorValue (), MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces), MakeObjectVectorChecker ()) + + .AddTraceSource ("SendOutgoing", "A newly-generated by this node ipv4 packet is about to be queued for transmission", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_sendOutgoingTrace)) + .AddTraceSource ("UnicastForward", "A unicast ipv4 packet was received by this node and is being forwarded to another node", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_unicastForwardTrace)) + .AddTraceSource ("LocalDeliver", "An ipv4 packet was received by/for this node, and it is being forward up the stack", + MakeTraceSourceAccessor (&Ipv4L3Protocol::m_localDeliverTrace)) + ; return tid; } @@ -369,7 +377,7 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr Ptr ipv4Interface; for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); - i++) + i++, interface++) { ipv4Interface = *i; if (ipv4Interface->GetDevice () == device) @@ -382,11 +390,12 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr else { NS_LOG_LOGIC ("Dropping received packet-- interface is down"); - m_dropTrace (packet); + Ipv4Header ipHeader; + packet->RemoveHeader (ipHeader); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); return; } } - interface++; } Ipv4Header ipHeader; @@ -398,7 +407,7 @@ Ipv4L3Protocol::Receive( Ptr device, Ptr p, uint16_t pr if (!ipHeader.IsChecksumOk ()) { - m_dropTrace (packet); + m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, interface); return; } @@ -477,6 +486,8 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr packetCopy = packet->Copy (); NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice()->GetMtu ()); + + m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); packetCopy->AddHeader (ipHeader); m_txTrace (packetCopy, ifaceIndex); outInterface->Send (packetCopy, destination); @@ -501,6 +512,7 @@ Ipv4L3Protocol::Send (Ptr packet, ttl = 1; ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment); Ptr packetCopy = packet->Copy (); + m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex); packetCopy->AddHeader (ipHeader); m_txTrace (packetCopy, ifaceIndex); outInterface->Send (packetCopy, destination); @@ -515,6 +527,8 @@ Ipv4L3Protocol::Send (Ptr packet, { NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route"); ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment); + int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ()); + m_sendOutgoingTrace (ipHeader, packet, interface); SendRealOut (route, packet, ipHeader); return; } @@ -535,12 +549,14 @@ Ipv4L3Protocol::Send (Ptr packet, Ptr newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_); if (newRoute) { + int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ()); + m_sendOutgoingTrace (ipHeader, packet, interface); SendRealOut (newRoute, packet, ipHeader); } else { NS_LOG_WARN ("No route to host. Drop."); - m_dropTrace (packet); + m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, 0); } } @@ -590,16 +606,13 @@ Ipv4L3Protocol::SendRealOut (Ptr route, { NS_LOG_FUNCTION (this << packet << &ipHeader); - // We add a header regardless of whether there is a route, since - // we may want to drop trace - packet->AddHeader (ipHeader); if (route == 0) { NS_LOG_WARN ("No route to host. Drop."); - m_dropTrace (packet); + m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, 0); return; } - + packet->AddHeader (ipHeader); Ptr outDev = route->GetOutputDevice (); int32_t interface = GetInterfaceForDevice (outDev); NS_ASSERT (interface >= 0); @@ -618,7 +631,9 @@ Ipv4L3Protocol::SendRealOut (Ptr route, else { NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ()); - m_dropTrace (packet); + Ipv4Header ipHeader; + packet->RemoveHeader (ipHeader); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); } } else @@ -632,7 +647,9 @@ Ipv4L3Protocol::SendRealOut (Ptr route, else { NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ()); - m_dropTrace (packet); + Ipv4Header ipHeader; + packet->RemoveHeader (ipHeader); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); } } } @@ -655,7 +672,7 @@ Ipv4L3Protocol::IpMulticastForward (Ptr mrtentry, Ptr rtentry, Ptr p, const Ip // Forwarding Ipv4Header ipHeader = header; Ptr packet = p->Copy (); + int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ()); ipHeader.SetTtl (ipHeader.GetTtl () - 1); if (ipHeader.GetTtl () == 0) { @@ -691,9 +709,10 @@ Ipv4L3Protocol::IpForward (Ptr rtentry, Ptr p, const Ip icmp->SendTimeExceededTtl (ipHeader, packet); } NS_LOG_WARN ("TTL exceeded. Drop."); - m_dropTrace (packet); + m_dropTrace (header, packet, DROP_TTL_EXPIRED, interface); return; } + m_unicastForwardTrace (ipHeader, packet, interface); SendRealOut (rtentry, packet, ipHeader); } @@ -703,6 +722,8 @@ Ipv4L3Protocol::LocalDeliver (Ptr packet, Ipv4Header const&ip, uin NS_LOG_FUNCTION (this << packet << &ip); Ptr p = packet->Copy (); // need to pass a non-const packet up + m_localDeliverTrace (ip, packet, iif); + Ptr protocol = GetProtocol (ip.GetProtocol ()); if (protocol != 0) { @@ -891,7 +912,7 @@ Ipv4L3Protocol::RouteInputError (Ptr p, const Ipv4Header & ipHeade { NS_LOG_FUNCTION (this << p << ipHeader << sockErrno); NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno); - m_dropTrace (p); + m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, 0); } diff --git a/src/internet-stack/ipv4-l3-protocol.h b/src/internet-stack/ipv4-l3-protocol.h index a95999778..46d61dc9e 100644 --- a/src/internet-stack/ipv4-l3-protocol.h +++ b/src/internet-stack/ipv4-l3-protocol.h @@ -63,6 +63,15 @@ public: Ipv4L3Protocol(); virtual ~Ipv4L3Protocol (); + enum DropReason + { + DROP_TTL_EXPIRED = 1, + DROP_NO_ROUTE, + DROP_BAD_CHECKSUM, + DROP_INTERFACE_DOWN, + DROP_ROUTE_ERROR, + }; + void SetNode (Ptr node); // functions defined in base class Ipv4 @@ -215,9 +224,15 @@ private: uint8_t m_defaultTtl; uint16_t m_identification; Ptr m_node; + + TracedCallback, uint32_t> m_sendOutgoingTrace; + TracedCallback, uint32_t> m_unicastForwardTrace; + TracedCallback, uint32_t> m_localDeliverTrace; + TracedCallback, uint32_t> m_txTrace; TracedCallback, uint32_t> m_rxTrace; - TracedCallback > m_dropTrace; + // (ifindex not valid if reason is DROP_NO_ROUTE) + TracedCallback, DropReason, uint32_t> m_dropTrace; Ptr m_routingProtocol; From b5842614271d62b16cf030cbc6add0c3afdf1ade Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 31 Aug 2009 18:50:38 +0100 Subject: [PATCH 2/8] Add a new 'flow-monitor' module. --- src/contrib/flow-monitor/design.txt | 43 ++ src/contrib/flow-monitor/flow-classifier.cc | 40 ++ src/contrib/flow-monitor/flow-classifier.h | 52 ++ src/contrib/flow-monitor/flow-monitor.cc | 468 ++++++++++++++++++ src/contrib/flow-monitor/flow-monitor.h | 138 ++++++ src/contrib/flow-monitor/flow-probe.cc | 111 +++++ src/contrib/flow-monitor/flow-probe.h | 74 +++ src/contrib/flow-monitor/histogram.cc | 212 ++++++++ src/contrib/flow-monitor/histogram.h | 64 +++ .../flow-monitor/ipv4-flow-classifier.cc | 203 ++++++++ .../flow-monitor/ipv4-flow-classifier.h | 74 +++ src/contrib/flow-monitor/ipv4-flow-probe.cc | 178 +++++++ src/contrib/flow-monitor/ipv4-flow-probe.h | 64 +++ src/contrib/flow-monitor/waf | 2 + src/contrib/flow-monitor/wscript | 23 + src/helper/flow-monitor-helper.cc | 110 ++++ src/helper/flow-monitor-helper.h | 56 +++ src/helper/wscript | 2 + src/wscript | 1 + 19 files changed, 1915 insertions(+) create mode 100644 src/contrib/flow-monitor/design.txt create mode 100644 src/contrib/flow-monitor/flow-classifier.cc create mode 100644 src/contrib/flow-monitor/flow-classifier.h create mode 100644 src/contrib/flow-monitor/flow-monitor.cc create mode 100644 src/contrib/flow-monitor/flow-monitor.h create mode 100644 src/contrib/flow-monitor/flow-probe.cc create mode 100644 src/contrib/flow-monitor/flow-probe.h create mode 100644 src/contrib/flow-monitor/histogram.cc create mode 100644 src/contrib/flow-monitor/histogram.h create mode 100644 src/contrib/flow-monitor/ipv4-flow-classifier.cc create mode 100644 src/contrib/flow-monitor/ipv4-flow-classifier.h create mode 100644 src/contrib/flow-monitor/ipv4-flow-probe.cc create mode 100644 src/contrib/flow-monitor/ipv4-flow-probe.h create mode 100755 src/contrib/flow-monitor/waf create mode 100644 src/contrib/flow-monitor/wscript create mode 100644 src/helper/flow-monitor-helper.cc create mode 100644 src/helper/flow-monitor-helper.h diff --git a/src/contrib/flow-monitor/design.txt b/src/contrib/flow-monitor/design.txt new file mode 100644 index 000000000..1d711342b --- /dev/null +++ b/src/contrib/flow-monitor/design.txt @@ -0,0 +1,43 @@ + +* One FlowMonitor per simulation + +* One FlowClassifier per simulation + - Assigns integer simulation unique identifiers to each flow + - Contains a classification method that maps parameters + (e.g. packets or packet headers) to the corresponding flow + identifier; + - FlowClassifier is abstract, needs a concrete subclass + > Ipv4FlowClassifier + +* Typically (but not necessarily) one FlowProbe node + - Is responsible for acquiring the packet data + - Works with FlowClassifier + - FlowProbe is abstract, needs a concrete subclass + > Ipv4FlowProbe + - Ipv4FlowProbe needs a matching classifier, Ipv4FlowClassifier + +* One ProbeFlowStats object per simulation flow per FlowProbe + - Indexed by the FlowId + - Bytes + - Packets + - Delay from first probe until the packet is received in this probe + +* One EndToEndFlowStats object per flow per FlowMonitor + - Lost packets + - Lost bytes + - Bytes + - Packets + - End-to-end delays + + + + +TODO: + + 1. Configurable time when to start/stop monitor. ***DONE*** + 2. Possibly, detect packet losses also via "drop" trace sources + 3. FlowMonitor::FlowStats: add time duration metrics: first flow timestamp, last flow timestamp + > to calculate bitrates... ***DONE*** + 4. Measure delay jitter + 5. Histogram for delays/jitters/packet sizes + diff --git a/src/contrib/flow-monitor/flow-classifier.cc b/src/contrib/flow-monitor/flow-classifier.cc new file mode 100644 index 000000000..fb184101f --- /dev/null +++ b/src/contrib/flow-monitor/flow-classifier.cc @@ -0,0 +1,40 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "flow-classifier.h" + +namespace ns3 { + +FlowClassifier::FlowClassifier () + : + m_lastNewFlowId (0) +{ +} + + +FlowId +FlowClassifier::GetNewFlowId () +{ + return ++m_lastNewFlowId; +} + + +} // namespace ns3 + diff --git a/src/contrib/flow-monitor/flow-classifier.h b/src/contrib/flow-monitor/flow-classifier.h new file mode 100644 index 000000000..0029ef771 --- /dev/null +++ b/src/contrib/flow-monitor/flow-classifier.h @@ -0,0 +1,52 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#ifndef __FLOW_CLASSIFIER_H__ +#define __FLOW_CLASSIFIER_H__ + +#include "ns3/ref-count-base.h" +#include + +namespace ns3 { + +typedef uint32_t FlowId; +typedef uint32_t FlowPacketId; + + +class FlowClassifier : public RefCountBase +{ + FlowId m_lastNewFlowId; + +public: + + FlowClassifier (); + + virtual void SerializeToXmlStream (std::ostream &os, int indent) const = 0; + +protected: + FlowId GetNewFlowId (); + +}; + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/flow-monitor.cc b/src/contrib/flow-monitor/flow-monitor.cc new file mode 100644 index 000000000..9a6536f25 --- /dev/null +++ b/src/contrib/flow-monitor/flow-monitor.cc @@ -0,0 +1,468 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "flow-monitor.h" +#include "ns3/simulator.h" +#include "ns3/log.h" +#include "ns3/double.h" +#include +#include + +#define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' '; + +#define PERIODIC_CHECK_INTERVAL (Seconds (1)) + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("FlowMonitor"); + +NS_OBJECT_ENSURE_REGISTERED (FlowMonitor); + + +TypeId +FlowMonitor::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::FlowMonitor") + .SetParent () + .AddConstructor () + .AddAttribute ("MaxPerHopDelay", ("The maximum per-hop delay that should be considered. " + "Packets still not received after this delay are to be considered lost."), + TimeValue (Seconds (10.0)), + MakeTimeAccessor (&FlowMonitor::m_maxPerHopDelay), + MakeTimeChecker ()) + .AddAttribute ("StartTime", ("The time when the monitoring starts."), + TimeValue (Seconds (0.0)), + MakeTimeAccessor (&FlowMonitor::Start), + MakeTimeChecker ()) + .AddAttribute ("DelayBinWidth", ("The width used in the delay histogram."), + DoubleValue (0.001), + MakeDoubleAccessor (&FlowMonitor::m_delayBinWidth), + MakeDoubleChecker ()) + .AddAttribute ("JitterBinWidth", ("The width used in the jitter histogram."), + DoubleValue (0.001), + MakeDoubleAccessor (&FlowMonitor::m_jitterBinWidth), + MakeDoubleChecker ()) + .AddAttribute ("PacketSizeBinWidth", ("The width used in the packetSize histogram."), + DoubleValue (20), + MakeDoubleAccessor (&FlowMonitor::m_packetSizeBinWidth), + MakeDoubleChecker ()) + ; + return tid; +} + +TypeId +FlowMonitor::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +FlowMonitor::FlowMonitor () + : m_enabled (false) +{ + // m_histogramBinWidth=DEFAULT_BIN_WIDTH; +} + + +inline FlowMonitor::FlowStats& +FlowMonitor::GetStatsForFlow (FlowId flowId) +{ + std::map::iterator iter; + iter = m_flowStats.find (flowId); + if (iter == m_flowStats.end ()) + { + FlowMonitor::FlowStats &ref = m_flowStats[flowId]; + ref.delaySum = Seconds (0); + ref.jitterSum = Seconds (0); + ref.lastDelay = Seconds (0); + ref.txBytes = 0; + ref.rxBytes = 0; + ref.txPackets = 0; + ref.rxPackets = 0; + ref.lostPackets = 0; + ref.timesForwarded = 0; + ref.delayHistogram.SetDefaultBinWidth (m_delayBinWidth); + ref.jitterHistogram.SetDefaultBinWidth (m_jitterBinWidth); + ref.packetSizeHistogram.SetDefaultBinWidth (m_packetSizeBinWidth); + return ref; + } + else + { + return iter->second; + } +} + + +void +FlowMonitor::ReportFirstTx (Ptr probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize) +{ + if (!m_enabled) + { + return; + } + Time now = Simulator::Now (); + TrackedPacket &tracked = m_trackedPackets[std::make_pair (flowId, packetId)]; + tracked.firstSeenTime = now; + tracked.lastSeenTime = tracked.firstSeenTime; + tracked.timesForwarded = 0; + NS_LOG_DEBUG ("ReportFirstTx: adding tracked packet (flowId=" << flowId << ", packetId=" << packetId + << ")."); + + probe->AddPacketStats (flowId, packetSize, Seconds (0)); + + FlowStats &stats = GetStatsForFlow (flowId); + stats.txBytes += packetSize; + stats.txPackets++; + if (stats.txPackets == 1) + { + stats.timeFirstTxPacket = now; + } + stats.timeLastTxPacket = now; +} + + +void +FlowMonitor::ReportForwarding (Ptr probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize) +{ + if (!m_enabled) + { + return; + } + std::pair key (flowId, packetId); + TrackedPacketMap::iterator tracked = m_trackedPackets.find (key); + if (tracked == m_trackedPackets.end ()) + { + NS_LOG_WARN ("Received packet forward report (flowId=" << flowId << ", packetId=" << packetId + << ") but not known to be transmitted."); + return; + } + + tracked->second.timesForwarded++; + tracked->second.lastSeenTime = Simulator::Now (); + + Time delay = (Simulator::Now () - tracked->second.firstSeenTime); + probe->AddPacketStats (flowId, packetSize, delay); +} + + +void +FlowMonitor::ReportLastRx (Ptr probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize) +{ + if (!m_enabled) + { + return; + } + TrackedPacketMap::iterator tracked = m_trackedPackets.find (std::make_pair (flowId, packetId)); + if (tracked == m_trackedPackets.end ()) + { + NS_LOG_WARN ("Received packet last-tx report (flowId=" << flowId << ", packetId=" << packetId + << ") but not known to be transmitted."); + return; + } + + Time now = Simulator::Now (); + Time delay = (now - tracked->second.firstSeenTime); + probe->AddPacketStats (flowId, packetSize, delay); + + FlowStats &stats = GetStatsForFlow (flowId); + stats.delaySum += delay; + stats.delayHistogram.AddValue (delay.GetSeconds ()); + if (stats.rxPackets > 0 ) + { + Time jitter = stats.lastDelay - delay; + if (jitter > Seconds (0)) + { + stats.jitterSum += jitter; + stats.jitterHistogram.AddValue (jitter.GetSeconds ()); + } + else + { + stats.jitterSum -= jitter; + stats.jitterHistogram.AddValue (-jitter.GetSeconds()); + } + } + stats.lastDelay = delay; + + stats.rxBytes += packetSize; + stats.packetSizeHistogram.AddValue ((double) packetSize); + stats.rxPackets++; + if (stats.rxPackets == 1) + { + stats.timeFirstRxPacket = now; + } + stats.timeLastRxPacket = now; + stats.timesForwarded += tracked->second.timesForwarded; + + NS_LOG_DEBUG ("ReportLastTx: removing tracked packet (flowId=" + << flowId << ", packetId=" << packetId << ")."); + + m_trackedPackets.erase (tracked); // we don't need to track this packet anymore +} + +void +FlowMonitor::ReportDrop (Ptr probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize, + uint32_t reasonCode) +{ + if (!m_enabled) + { + return; + } + + probe->AddPacketDropStats (flowId, packetSize, reasonCode); + + FlowStats &stats = GetStatsForFlow (flowId); + stats.lostPackets++; + if (stats.packetsDropped.size () < reasonCode + 1) + { + stats.packetsDropped.resize (reasonCode + 1, 0); + stats.bytesDropped.resize (reasonCode + 1, 0); + } + ++stats.packetsDropped[reasonCode]; + stats.bytesDropped[reasonCode] += packetSize; + NS_LOG_DEBUG ("++stats.packetsDropped[" << reasonCode<< "]; // becomes: " << stats.packetsDropped[reasonCode]); + + TrackedPacketMap::iterator tracked = m_trackedPackets.find (std::make_pair (flowId, packetId)); + if (tracked != m_trackedPackets.end ()) + { + // we don't need to track this packet anymore + // FIXME: this will not necessarily be true with broadcast/multicast + NS_LOG_DEBUG ("ReportDrop: removing tracked packet (flowId=" + << flowId << ", packetId=" << packetId << ")."); + m_trackedPackets.erase (tracked); + } +} + +std::map +FlowMonitor::GetFlowStats () const +{ + return m_flowStats; +} + + +void +FlowMonitor::CheckForLostPackets (Time maxDelay) +{ + Time now = Simulator::Now (); + + for (TrackedPacketMap::iterator iter = m_trackedPackets.begin (); + iter != m_trackedPackets.end (); ) + { + if (now - iter->second.lastSeenTime >= maxDelay) + { + // packet is considered lost, add it to the loss statistics + std::map::iterator + flow = m_flowStats.find (iter->first.first); + NS_ASSERT (flow != m_flowStats.end ()); + flow->second.lostPackets++; + + // we won't track it anymore + m_trackedPackets.erase (iter++); + } + else + { + iter++; + } + } +} + +void +FlowMonitor::CheckForLostPackets () +{ + CheckForLostPackets (m_maxPerHopDelay); +} + +void +FlowMonitor::PeriodicCheckForLostPackets () +{ + CheckForLostPackets (); + Simulator::Schedule (PERIODIC_CHECK_INTERVAL, &FlowMonitor::PeriodicCheckForLostPackets, this); +} + +void +FlowMonitor::NotifyConstructionCompleted () +{ + Object::NotifyConstructionCompleted (); + Simulator::Schedule (PERIODIC_CHECK_INTERVAL, &FlowMonitor::PeriodicCheckForLostPackets, this); +} + +void +FlowMonitor::AddProbe (Ptr probe) +{ + m_flowProbes.push_back (probe); +} + +std::vector< Ptr > +FlowMonitor::GetAllProbes () const +{ + return m_flowProbes; +} + + +void +FlowMonitor::Start (const Time &time) +{ + if (m_enabled) + { + return; + } + Simulator::Cancel (m_startEvent); + m_startEvent = Simulator::Schedule (time, &FlowMonitor::StartRightNow, Ptr (this)); +} + +void +FlowMonitor::Stop (const Time &time) +{ + if (!m_enabled) + { + return; + } + Simulator::Cancel (m_stopEvent); + m_stopEvent = Simulator::Schedule (time, &FlowMonitor::StopRightNow, Ptr (this)); +} + + +void +FlowMonitor::StartRightNow () +{ + if (m_enabled) + { + return; + } + m_enabled = true; +} + + +void +FlowMonitor::StopRightNow () +{ + if (!m_enabled) + { + return; + } + m_enabled = false; + CheckForLostPackets (); +} + +void +FlowMonitor::SetFlowClassifier (Ptr classifier) +{ + m_classifier = classifier; +} + +void +FlowMonitor::SerializeToXmlStream (std::ostream &os, int indent, bool enableHistograms, bool enableProbes) +{ + CheckForLostPackets (); + + INDENT(indent); os << "\n"; + indent += 2; + INDENT(indent); os << "\n"; + indent += 2; + for (std::map::const_iterator flowI = m_flowStats.begin (); + flowI != m_flowStats.end (); flowI++) + { + + INDENT(indent); +#define ATTRIB(name) << " "#name"=\"" << flowI->second.name << "\"" + os << "first << "\"" + ATTRIB(timeFirstTxPacket) + ATTRIB(timeFirstRxPacket) + ATTRIB(timeLastTxPacket) + ATTRIB(timeLastRxPacket) + ATTRIB(delaySum) + ATTRIB(jitterSum) + ATTRIB(lastDelay) + ATTRIB(txBytes) + ATTRIB(rxBytes) + ATTRIB(txPackets) + ATTRIB(rxPackets) + ATTRIB(lostPackets) + ATTRIB(timesForwarded) + << ">\n"; +#undef ATTRIB + + + indent += 2; + for (uint32_t reasonCode = 0; reasonCode < flowI->second.packetsDropped.size (); reasonCode++) + { + INDENT(indent); + os << "second.packetsDropped[reasonCode] + << "\" />\n"; + } + for (uint32_t reasonCode = 0; reasonCode < flowI->second.bytesDropped.size (); reasonCode++) + { + INDENT(indent); + os << "second.bytesDropped[reasonCode] + << "\" />\n"; + } + if (enableHistograms) + { + flowI->second.delayHistogram.SerializeToXmlStream (os, indent, "delayHistogram"); + flowI->second.jitterHistogram.SerializeToXmlStream (os, indent, "jitterHistogram"); + flowI->second.packetSizeHistogram.SerializeToXmlStream (os, indent, "packetSizeHistogram"); + } + indent -= 2; + + INDENT(indent); os << "\n"; + } + indent -= 2; + INDENT(indent); os << "\n"; + + m_classifier->SerializeToXmlStream (os, indent); + + if (enableProbes) + { + INDENT(indent); os << "\n"; + indent += 2; + for (uint32_t i = 0; i < m_flowProbes.size (); i++) + { + m_flowProbes[i]->SerializeToXmlStream (os, indent, i); + } + indent -= 2; + INDENT(indent); os << "\n"; + } + + indent -= 2; + INDENT(indent); os << "\n"; +} + + +std::string +FlowMonitor::SerializeToXmlString (int indent, bool enableHistograms, bool enableProbes) +{ + std::ostringstream os; + SerializeToXmlStream (os, indent, enableHistograms, enableProbes); + return os.str (); +} + + +void +FlowMonitor::SerializeToXmlFile (std::string fileName, bool enableHistograms, bool enableProbes) +{ + std::ofstream os (fileName.c_str (), std::ios::out|std::ios::binary); + os << "\n"; + SerializeToXmlStream (os, 0, enableHistograms, enableProbes); + os.close (); +} + + +} // namespace ns3 + diff --git a/src/contrib/flow-monitor/flow-monitor.h b/src/contrib/flow-monitor/flow-monitor.h new file mode 100644 index 000000000..d1acc8fcc --- /dev/null +++ b/src/contrib/flow-monitor/flow-monitor.h @@ -0,0 +1,138 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#ifndef __FLOW_MONITOR_H__ +#define __FLOW_MONITOR_H__ + +#include +#include + +#include "ns3/ptr.h" +#include "ns3/object.h" +#include "ns3/flow-probe.h" +#include "ns3/flow-classifier.h" +#include "ns3/histogram.h" +#include "ns3/nstime.h" +#include "ns3/event-id.h" + +namespace ns3 { + + +class FlowMonitor : public Object +{ +public: + + struct FlowStats + { + Time timeFirstTxPacket; + Time timeFirstRxPacket; + Time timeLastTxPacket; + Time timeLastRxPacket; + Time delaySum; // delayCount == rxPackets + Time jitterSum; // jitterCount == rxPackets - 1 + Time lastDelay; + uint64_t txBytes; + uint64_t rxBytes; + uint32_t txPackets; + uint32_t rxPackets; + uint32_t lostPackets; + uint32_t timesForwarded; // number of times a packet was forwarded, summed for all received packets + Histogram delayHistogram; + Histogram jitterHistogram; + Histogram packetSizeHistogram; + std::vector packetsDropped; // packetsDropped[reasonCode] => number of dropped packets + std::vector bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes + }; + + // --- basic methods --- + static TypeId GetTypeId (); + TypeId GetInstanceTypeId () const; + FlowMonitor (); + void SetFlowClassifier (Ptr classifier); + + void Start (const Time &time); + void Stop (const Time &time); + void StartRightNow (); + void StopRightNow (); + + // --- methods to be used by the FlowMonitorProbe's only --- + void AddProbe (Ptr probe); + void ReportFirstTx (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + void ReportForwarding (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + void ReportLastRx (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + void ReportDrop (Ptr probe, FlowId flowId, FlowPacketId packetId, + uint32_t packetSize, uint32_t reasonCode); + + + /// Check right now for packets that appear to be lost + void CheckForLostPackets (); + void CheckForLostPackets (Time maxDelay); + + // --- methods to get the results --- + // remember to call CheckForLostPackets first! + std::map GetFlowStats () const; + std::vector< Ptr > GetAllProbes () const; + + void SerializeToXmlStream (std::ostream &os, int indent, bool enableHistograms, bool enableProbes); + std::string SerializeToXmlString (int indent, bool enableHistograms, bool enableProbes); + void SerializeToXmlFile (std::string fileName, bool enableHistograms, bool enableProbes); + + +protected: + + virtual void NotifyConstructionCompleted (); + +private: + + struct TrackedPacket + { + Time firstSeenTime; // absolute time when the packet was first seen by a probe + Time lastSeenTime; // absolute time when the packet was last seen by a probe + uint32_t timesForwarded; // number of times the packet was reportedly forwarded + }; + + // FlowId --> FlowStats + std::map m_flowStats; + + // (FlowId,PacketId) --> TrackedPacket + typedef std::map< std::pair, TrackedPacket> TrackedPacketMap; + TrackedPacketMap m_trackedPackets; + Time m_maxPerHopDelay; + std::vector< Ptr > m_flowProbes; + + // note: this is needed only for serialization + Ptr m_classifier; + + EventId m_startEvent; + EventId m_stopEvent; + bool m_enabled; + double m_delayBinWidth; + double m_jitterBinWidth; + double m_packetSizeBinWidth; + + FlowStats& GetStatsForFlow (FlowId flowId); + void PeriodicCheckForLostPackets (); +}; + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/flow-probe.cc b/src/contrib/flow-monitor/flow-probe.cc new file mode 100644 index 000000000..e58058942 --- /dev/null +++ b/src/contrib/flow-monitor/flow-probe.cc @@ -0,0 +1,111 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "ns3/flow-probe.h" +#include "ns3/flow-monitor.h" + +namespace ns3 { + + +FlowProbe::~FlowProbe () +{ +} + + +FlowProbe::FlowProbe (Ptr flowMonitor) + : m_flowMonitor (flowMonitor) +{ + m_flowMonitor->AddProbe (this); +} + +void +FlowProbe::AddPacketStats (FlowId flowId, uint32_t packetSize, Time delayFromFirstProbe) +{ + FlowStats &flow = m_stats[flowId]; + flow.delayFromFirstProbeSum += delayFromFirstProbe; + flow.bytes += packetSize; + ++flow.packets; +} + +void +FlowProbe::AddPacketDropStats (FlowId flowId, uint32_t packetSize, uint32_t reasonCode) +{ + FlowStats &flow = m_stats[flowId]; + + if (flow.packetsDropped.size () < reasonCode + 1) + { + flow.packetsDropped.resize (reasonCode + 1, 0); + flow.bytesDropped.resize (reasonCode + 1, 0); + } + ++flow.packetsDropped[reasonCode]; + flow.bytesDropped[reasonCode] += packetSize; +} + +FlowProbe::Stats +FlowProbe::GetStats () const +{ + return m_stats; +} + +void +FlowProbe::SerializeToXmlStream (std::ostream &os, int indent, uint32_t index) const +{ + #define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' '; + + INDENT(indent); os << "\n"; + + indent += 2; + + for (Stats::const_iterator iter = m_stats.begin (); iter != m_stats.end (); iter++) + { + INDENT(indent); + os << "first << "\"" + << " packets=\"" << iter->second.packets << "\"" + << " bytes=\"" << iter->second.bytes << "\"" + << " delayFromFirstProbeSum=\"" << iter->second.delayFromFirstProbeSum << "\"" + << " >\n"; + indent += 2; + for (uint32_t reasonCode = 0; reasonCode < iter->second.packetsDropped.size (); reasonCode++) + { + INDENT(indent); + os << "second.packetsDropped[reasonCode] + << "\" />\n"; + } + for (uint32_t reasonCode = 0; reasonCode < iter->second.bytesDropped.size (); reasonCode++) + { + INDENT(indent); + os << "second.bytesDropped[reasonCode] + << "\" />\n"; + } + indent -= 2; + INDENT(indent); os << "\n"; + } + indent -= 2; + INDENT(indent); os << "\n"; +} + + + +} // namespace ns3 + + diff --git a/src/contrib/flow-monitor/flow-probe.h b/src/contrib/flow-monitor/flow-probe.h new file mode 100644 index 000000000..3b86f16b7 --- /dev/null +++ b/src/contrib/flow-monitor/flow-probe.h @@ -0,0 +1,74 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#ifndef __FLOW_PROBE_H__ +#define __FLOW_PROBE_H__ + +#include +#include + +#include "ns3/ref-count-base.h" +#include "ns3/flow-classifier.h" +#include "ns3/nstime.h" + +namespace ns3 { + +class FlowMonitor; + + +class FlowProbe : public RefCountBase +{ +protected: + + FlowProbe (Ptr flowMonitor); + +public: + ~FlowProbe (); + + struct FlowStats + { + FlowStats () : delayFromFirstProbeSum (Seconds (0)), bytes (0), packets (0) {} + + std::vector packetsDropped; // packetsDropped[reasonCode] => number of dropped packets + std::vector bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes + Time delayFromFirstProbeSum; // divide by 'Scalar (packets)' to get the average delay + uint64_t bytes; + uint32_t packets; + }; + + typedef std::map Stats; + + void AddPacketStats (FlowId flowId, uint32_t packetSize, Time delayFromFirstProbe); + void AddPacketDropStats (FlowId flowId, uint32_t packetSize, uint32_t reasonCode); + Stats GetStats () const; + + void SerializeToXmlStream (std::ostream &os, int indent, uint32_t index) const; + +protected: + Ptr m_flowMonitor; + Stats m_stats; + +}; + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/histogram.cc b/src/contrib/flow-monitor/histogram.cc new file mode 100644 index 000000000..ec1b31190 --- /dev/null +++ b/src/contrib/flow-monitor/histogram.cc @@ -0,0 +1,212 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Pedro Fortuna +// + +#include +#include "histogram.h" +#include "ns3/simulator.h" +#include "ns3/log.h" + +#define DEFAULT_BIN_WIDTH 1 +// #define RESERVED_BINS_INC 10 + + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("Histogram"); + +// uint32_t +// Histogram::GetSize () const +// { +// return m_histogram.size (); +// } + +uint32_t +Histogram::GetNBins () const +{ + return m_histogram.size (); +} + +double +Histogram::GetBinStart (uint32_t index) +{ + return index*m_binWidth; +} + +double +Histogram::GetBinEnd (uint32_t index) +{ + return (index + 1) * m_binWidth; +} + +double +Histogram::GetBinWidth (uint32_t index) const +{ + return m_binWidth; +} + +void +Histogram::SetDefaultBinWidth (double binWidth) +{ + NS_ASSERT (m_histogram.size () == 0); //we can only change the bin width if no values were added + m_binWidth = binWidth; +} + +uint32_t +Histogram::GetBinCount (uint32_t index) +{ + NS_ASSERT (index < m_histogram.size ()); + return m_histogram[index]; +} + +void +Histogram::AddValue (double value) +{ + uint32_t index = floor (value/m_binWidth); + + //check if we need to resize the vector + NS_LOG_DEBUG ("AddValue: index=" << index << ", m_histogram.size()=" << m_histogram.size ()); + + if (index >= m_histogram.size ()) + { + m_histogram.resize (index + 1, 0); + } + m_histogram[index]++; +} + +Histogram::Histogram (double binWidth) +{ + m_binWidth = binWidth; +} + +Histogram::Histogram () +{ + Histogram (DEFAULT_BIN_WIDTH); +} + + +void +Histogram::SerializeToXmlStream (std::ostream &os, int indent, std::string elementName) const +{ +#define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' '; + + INDENT(indent); os << "<" << elementName // << " binWidth=\"" << m_binWidth << "\"" + << " nBins=\"" << m_histogram.size () << "\"" + << " >\n"; + indent += 2; + +#if 1 // two alternative forms of representing bin data, one more verbose than the other one + for (uint32_t index = 0; index < m_histogram.size (); index++) + { + if (m_histogram[index]) + { + INDENT(indent); + os << "\n"; + } + } +#else + INDENT(indent + 2); + for (uint32_t index = 0; index < m_histogram.size (); index++) + { + if (index > 0) + { + os << " "; + } + os << m_histogram[index]; + } + os << "\n"; +#endif + indent -= 2; + INDENT(indent); os << "\n"; +#undef INDENT +} + + + + +} // namespace ns3 + + +#ifdef RUN_SELF_TESTS + +#include "ns3/test.h" + +namespace ns3 { + +class HistogramTest : public ns3::Test { +private: +public: + HistogramTest (); + virtual bool RunTests (void); + + +}; + +HistogramTest::HistogramTest () + : ns3::Test ("Histogram") +{} + + +bool +HistogramTest::RunTests (void) +{ + bool result = true; + + Histogram h0(3.5); + // Testing floating-point bin widths + { + for (int i=1; i<= 10; i++) h0.AddValue(3.4); + for (int i=1; i<= 5; i++) h0.AddValue(3.6); + + NS_TEST_ASSERT_EQUAL (h0.GetBinWidth (0), 3.5); + NS_TEST_ASSERT_EQUAL (h0.GetNBins (), 2); + NS_TEST_ASSERT_EQUAL (h0.GetBinStart(1), 3.5); + NS_TEST_ASSERT_EQUAL (h0.GetBinCount(0), 10); + NS_TEST_ASSERT_EQUAL (h0.GetBinCount(1), 5); + } + + { + // Testing bin expansion + h0.AddValue(74.3); + + NS_TEST_ASSERT_EQUAL (h0.GetNBins (), 22); + + /*for (uint32_t i=0; i < h0.GetSize () ; i++) + { + std::cout << i << ") BinStart:" << h0.GetBinStart (i) << " BinEnd:" << ((double) h0.GetBinStart (i) + h0.GetBinWidth (i)) << " BinCount: " << h0.GetBinCount (i) << std::endl; + }*/ + + NS_TEST_ASSERT_EQUAL (h0.GetBinCount (21), 1); + } + + return result; +} + +static HistogramTest gHistogramTest; + +}; // namespace + + +#endif /* RUN_SELF_TESTS */ + diff --git a/src/contrib/flow-monitor/histogram.h b/src/contrib/flow-monitor/histogram.h new file mode 100644 index 000000000..6772e1675 --- /dev/null +++ b/src/contrib/flow-monitor/histogram.h @@ -0,0 +1,64 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Pedro Fortuna +// + +#ifndef __NS3_HISTOGRAM_H__ +#define __NS3_HISTOGRAM_H__ + +#include +#include +#include + +namespace ns3 { + +class Histogram +{ +public: + + // --- basic methods --- + Histogram (double binWidth); + Histogram (); + + // Methods for Getting the Histogram Results + uint32_t GetNBins () const; + double GetBinStart (uint32_t index); + double GetBinEnd (uint32_t index); + double GetBinWidth (uint32_t index) const; + void SetDefaultBinWidth (double binWidth); + uint32_t GetBinCount (uint32_t index); + + // Method for adding values + void AddValue (double value); + + + void SerializeToXmlStream (std::ostream &os, int indent, std::string elementName) const; + + // TODO: add method(s) to estimate N, µ, and s² from the histogram, + // see http://www.dspguide.com/ch2/4.htm + +private: + std::vector m_histogram; + double m_binWidth; +}; + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/ipv4-flow-classifier.cc b/src/contrib/flow-monitor/ipv4-flow-classifier.cc new file mode 100644 index 000000000..e0692bf21 --- /dev/null +++ b/src/contrib/flow-monitor/ipv4-flow-classifier.cc @@ -0,0 +1,203 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "ns3/packet.h" + +#include "ipv4-flow-classifier.h" +#include "ns3/udp-header.h" +#include "ns3/tcp-header.h" + +namespace ns3 { + +/* see http://www.iana.org/assignments/protocol-numbers */ +const uint8_t TCP_PROT_NUMBER = 6; +const uint8_t UDP_PROT_NUMBER = 17; + + + +bool operator < (const Ipv4FlowClassifier::FiveTuple &t1, + const Ipv4FlowClassifier::FiveTuple &t2) +{ + if (t1.sourceAddress < t2.sourceAddress) + { + return true; + } + if (t1.sourceAddress != t2.sourceAddress) + { + return false; + } + + if (t1.destinationAddress < t2.destinationAddress) + { + return true; + } + if (t1.destinationAddress != t2.destinationAddress) + { + return false; + } + + if (t1.protocol < t2.protocol) + { + return true; + } + if (t1.protocol != t2.protocol) + { + return false; + } + + if (t1.sourcePort < t2.sourcePort) + { + return true; + } + if (t1.sourcePort != t2.sourcePort) + { + return false; + } + + if (t1.destinationPort < t2.destinationPort) + { + return true; + } + if (t1.destinationPort != t2.destinationPort) + { + return false; + } + + return false; +} + +bool operator == (const Ipv4FlowClassifier::FiveTuple &t1, + const Ipv4FlowClassifier::FiveTuple &t2) +{ + return (t1.sourceAddress == t2.sourceAddress && + t1.destinationAddress == t2.destinationAddress && + t1.protocol == t2.protocol && + t1.sourcePort == t2.sourcePort && + t1.destinationPort == t2.destinationPort); +} + + + +Ipv4FlowClassifier::Ipv4FlowClassifier () +{ +} + +bool +Ipv4FlowClassifier::Classify (const Ipv4Header &ipHeader, Ptr ipPayload, + uint32_t *out_flowId, uint32_t *out_packetId) +{ + if (ipHeader.GetDestination () == Ipv4Address::GetBroadcast ()) + { + // we are not prepared to handle broadcast yet + return false; + } + + FiveTuple tuple; + tuple.sourceAddress = ipHeader.GetSource (); + tuple.destinationAddress = ipHeader.GetDestination (); + tuple.protocol = ipHeader.GetProtocol (); + + switch (tuple.protocol) + { + case UDP_PROT_NUMBER: + { + UdpHeader udpHeader; + ipPayload->PeekHeader (udpHeader); + tuple.sourcePort = udpHeader.GetSourcePort (); + tuple.destinationPort = udpHeader.GetDestinationPort (); + } + break; + + case TCP_PROT_NUMBER: + { + TcpHeader tcpHeader; + ipPayload->PeekHeader (tcpHeader); + tuple.sourcePort = tcpHeader.GetSourcePort (); + tuple.destinationPort = tcpHeader.GetDestinationPort (); + } + break; + + default: + return false; + } + + // try to insert the tuple, but check if it already exists + std::pair::iterator, bool> insert + = m_flowMap.insert (std::pair (tuple, 0)); + + // if the insertion succeeded, we need to assign this tuple a new flow identifier + if (insert.second) + { + insert.first->second = GetNewFlowId (); + } + + *out_flowId = insert.first->second; + *out_packetId = ipHeader.GetIdentification (); + + return true; +} + + +Ipv4FlowClassifier::FiveTuple +Ipv4FlowClassifier::FindFlow (FlowId flowId) const +{ + for (std::map::const_iterator + iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++) + { + if (iter->second == flowId) + { + return iter->first; + } + } + NS_FATAL_ERROR ("Could not find the flow with ID " << flowId); + FiveTuple retval = { Ipv4Address::GetZero (), Ipv4Address::GetZero (), 0, 0, 0 }; + return retval; +} + +void +Ipv4FlowClassifier::SerializeToXmlStream (std::ostream &os, int indent) const +{ +#define INDENT(level) for (int __xpto = 0; __xpto < level; __xpto++) os << ' '; + + INDENT(indent); os << "\n"; + + indent += 2; + for (std::map::const_iterator + iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++) + { + INDENT(indent); + os << "second << "\"" + << " sourceAddress=\"" << iter->first.sourceAddress << "\"" + << " destinationAddress=\"" << iter->first.destinationAddress << "\"" + << " protocol=\"" << int(iter->first.protocol) << "\"" + << " sourcePort=\"" << iter->first.sourcePort << "\"" + << " destinationPort=\"" << iter->first.destinationPort << "\"" + << " />\n"; + } + + indent -= 2; + INDENT(indent); os << "\n"; + +#undef INDENT +} + + +} // namespace ns3 + diff --git a/src/contrib/flow-monitor/ipv4-flow-classifier.h b/src/contrib/flow-monitor/ipv4-flow-classifier.h new file mode 100644 index 000000000..fff4baa71 --- /dev/null +++ b/src/contrib/flow-monitor/ipv4-flow-classifier.h @@ -0,0 +1,74 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#ifndef __IPV4_FLOW_CLASSIFIER_H__ +#define __IPV4_FLOW_CLASSIFIER_H__ + +#include +#include + +#include "ns3/ipv4-header.h" +#include "ns3/flow-classifier.h" + +namespace ns3 { + +class Packet; + +class Ipv4FlowClassifier : public FlowClassifier +{ +public: + + struct FiveTuple + { + Ipv4Address sourceAddress; + Ipv4Address destinationAddress; + uint8_t protocol; + uint16_t sourcePort; + uint16_t destinationPort; + }; + + Ipv4FlowClassifier (); + + /// \brief try to classify the packet into flow-id and packet-id + /// \return true if the packet was classified, false if not (i.e. it + /// does not appear to be part of a flow). + bool Classify (const Ipv4Header &ipHeader, Ptr ipPayload, + uint32_t *out_flowId, uint32_t *out_packetId); + + /// Searches for the FiveTuple corresponding to the given flowId + FiveTuple FindFlow (FlowId flowId) const; + + virtual void SerializeToXmlStream (std::ostream &os, int indent) const; + +private: + + std::map m_flowMap; + +}; + + +bool operator < (const Ipv4FlowClassifier::FiveTuple &t1, const Ipv4FlowClassifier::FiveTuple &t2); +bool operator == (const Ipv4FlowClassifier::FiveTuple &t1, const Ipv4FlowClassifier::FiveTuple &t2); + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/ipv4-flow-probe.cc b/src/contrib/flow-monitor/ipv4-flow-probe.cc new file mode 100644 index 000000000..1139641ec --- /dev/null +++ b/src/contrib/flow-monitor/ipv4-flow-probe.cc @@ -0,0 +1,178 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "ns3/ipv4-flow-probe.h" +#include "ns3/ipv4-flow-classifier.h" +#include "ns3/node.h" +#include "ns3/packet.h" +#include "ns3/flow-monitor.h" +#include "ns3/log.h" +#include "ns3/pointer.h" + +namespace ns3 { + +NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe"); + + +Ipv4FlowProbe::~Ipv4FlowProbe () +{ +} + + +Ipv4FlowProbe::Ipv4FlowProbe (Ptr monitor, + Ptr classifier, + Ptr node) + : FlowProbe (monitor), + m_classifier (classifier) +{ + NS_LOG_FUNCTION (this << node->GetId ()); + + Ptr ipv4 = node->GetObject (); + + if (!ipv4->TraceConnectWithoutContext ("SendOutgoing", + MakeCallback (&Ipv4FlowProbe::SendOutgoingLogger, Ptr (this)))) + { + NS_FATAL_ERROR ("trace fail"); + } + if (!ipv4->TraceConnectWithoutContext ("UnicastForward", + MakeCallback (&Ipv4FlowProbe::ForwardLogger, Ptr (this)))) + { + NS_FATAL_ERROR ("trace fail"); + } + if (!ipv4->TraceConnectWithoutContext ("LocalDeliver", + MakeCallback (&Ipv4FlowProbe::ForwardUpLogger, Ptr (this)))) + { + NS_FATAL_ERROR ("trace fail"); + } + + if (!ipv4->TraceConnectWithoutContext ("Drop", + MakeCallback (&Ipv4FlowProbe::DropLogger, Ptr (this)))) + { + NS_FATAL_ERROR ("trace fail"); + } +} + +void +Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface) +{ + FlowId flowId; + FlowPacketId packetId; + + if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId)) + { + uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); + NS_LOG_DEBUG ("ReportFirstTx ("<ReportFirstTx (this, flowId, packetId, size); + } +} + +void +Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface) +{ + FlowId flowId; + FlowPacketId packetId; + + if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId)) + { + uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); + NS_LOG_DEBUG ("ReportForwarding ("<ReportForwarding (this, flowId, packetId, size); + } + +} + +void +Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface) +{ + FlowId flowId; + FlowPacketId packetId; + + if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId)) + { + uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); + NS_LOG_DEBUG ("ReportLastRx ("<ReportLastRx (this, flowId, packetId, size); + } +} + +void +Ipv4FlowProbe::DropLogger (const Ipv4Header &ipHeader, Ptr ipPayload, + Ipv4L3Protocol::DropReason reason, uint32_t ifIndex) +{ +#if 0 + switch (reason) + { + case Ipv4L3Protocol::DROP_NO_ROUTE: + break; + + case Ipv4L3Protocol::DROP_TTL_EXPIRED: + case Ipv4L3Protocol::DROP_BAD_CHECKSUM: + Ipv4Address addri = m_ipv4->GetAddress (ifIndex); + Ipv4Mask maski = m_ipv4->GetNetworkMask (ifIndex); + Ipv4Address bcast = addri.GetSubnetDirectedBroadcast (maski); + if (ipHeader.GetDestination () == bcast) // we don't want broadcast packets + { + return; + } + } +#endif + + FlowId flowId; + FlowPacketId packetId; + + if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId)) + { + uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ()); + NS_LOG_DEBUG ("Drop ("<ReportDrop (this, flowId, packetId, size, myReason); + } +} + + + +} // namespace ns3 + + diff --git a/src/contrib/flow-monitor/ipv4-flow-probe.h b/src/contrib/flow-monitor/ipv4-flow-probe.h new file mode 100644 index 000000000..4248f771e --- /dev/null +++ b/src/contrib/flow-monitor/ipv4-flow-probe.h @@ -0,0 +1,64 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#ifndef __IPV4_FLOW_PROBE_H__ +#define __IPV4_FLOW_PROBE_H__ + +#include "ns3/flow-probe.h" +#include "ns3/ipv4-flow-classifier.h" +#include "ns3/ipv4-l3-protocol.h" + +namespace ns3 { + +class FlowMonitor; +class Node; + +class Ipv4FlowProbe : public FlowProbe +{ + +public: + Ipv4FlowProbe (Ptr monitor, Ptr classifier, Ptr node); + ~Ipv4FlowProbe (); + + enum DropReason + { + DROP_NO_ROUTE = 0, + DROP_TTL_EXPIRE, + DROP_BAD_CHECKSUM, + // DROP_QUEUE, // TODO: this is not easy to do + DROP_INVALID_REASON, + }; + +private: + + void SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface); + void ForwardLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface); + void ForwardUpLogger (const Ipv4Header &ipHeader, Ptr ipPayload, uint32_t interface); + void DropLogger (const Ipv4Header &ipHeader, Ptr ipPayload, + Ipv4L3Protocol::DropReason reason, uint32_t ifIndex); + + Ptr m_classifier; +}; + + +} // namespace ns3 + +#endif + diff --git a/src/contrib/flow-monitor/waf b/src/contrib/flow-monitor/waf new file mode 100755 index 000000000..51f099826 --- /dev/null +++ b/src/contrib/flow-monitor/waf @@ -0,0 +1,2 @@ +#! /bin/sh +exec "`dirname "$0"`"/../../../waf "$@" diff --git a/src/contrib/flow-monitor/wscript b/src/contrib/flow-monitor/wscript new file mode 100644 index 000000000..71872a8da --- /dev/null +++ b/src/contrib/flow-monitor/wscript @@ -0,0 +1,23 @@ +## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*- + +def build(bld): + obj = bld.create_ns3_module('flow-monitor', ['internet-stack']) + obj.source = [ + 'flow-monitor.cc', + 'flow-classifier.cc', + 'flow-probe.cc', + 'ipv4-flow-classifier.cc', + 'ipv4-flow-probe.cc', + 'histogram.cc', + ] + headers = bld.new_task_gen('ns3header') + headers.module = 'flow-monitor' + headers.source = [ + 'flow-monitor.h', + 'flow-probe.h', + 'flow-classifier.h', + 'ipv4-flow-classifier.h', + 'ipv4-flow-probe.h', + 'histogram.h', + ] + diff --git a/src/helper/flow-monitor-helper.cc b/src/helper/flow-monitor-helper.cc new file mode 100644 index 000000000..72c2bc0d0 --- /dev/null +++ b/src/helper/flow-monitor-helper.cc @@ -0,0 +1,110 @@ +// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// + +#include "flow-monitor-helper.h" + +#include "ns3/flow-monitor.h" +#include "ns3/ipv4-flow-classifier.h" +#include "ns3/ipv4-flow-probe.h" +#include "ns3/ipv4-l3-protocol.h" +#include "ns3/node.h" +#include "ns3/node-list.h" + + +namespace ns3 { + +FlowMonitorHelper::FlowMonitorHelper () +{ + m_monitorFactory.SetTypeId ("ns3::FlowMonitor"); +} + +void +FlowMonitorHelper::SetMonitorAttribute (std::string n1, const AttributeValue &v1) +{ + m_monitorFactory.Set (n1, v1); +} + + +Ptr +FlowMonitorHelper::GetMonitor () +{ + if (!m_flowMonitor) + { + m_flowMonitor = m_monitorFactory.Create (); + m_flowClassifier = Create (); + m_flowMonitor->SetFlowClassifier (m_flowClassifier); + } + return m_flowMonitor; +} + + +Ptr +FlowMonitorHelper::GetClassifier () +{ + if (!m_flowClassifier) + { + m_flowClassifier = Create (); + } + return m_flowClassifier; +} + + +Ptr +FlowMonitorHelper::Install (Ptr node) +{ + Ptr monitor = GetMonitor (); + Ptr classifier = GetClassifier (); + Ptr probe = Create (monitor, + DynamicCast (classifier), + node); + return m_flowMonitor; +} + + +Ptr +FlowMonitorHelper::Install (NodeContainer nodes) +{ + for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i) + { + Ptr node = *i; + if (node->GetObject ()) + { + Install (node); + } + } + return m_flowMonitor; +} + +Ptr +FlowMonitorHelper::InstallAll () +{ + for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i) + { + Ptr node = *i; + if (node->GetObject ()) + { + Install (node); + } + } + return m_flowMonitor; +} + + +} // namespace ns3 diff --git a/src/helper/flow-monitor-helper.h b/src/helper/flow-monitor-helper.h new file mode 100644 index 000000000..bdd4e99ac --- /dev/null +++ b/src/helper/flow-monitor-helper.h @@ -0,0 +1,56 @@ +// -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- +// +// Copyright (c) 2009 INESC Porto +// +// 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: Gustavo J. A. M. Carneiro +// +#ifndef FLOW_MONITOR_HELPER_H +#define FLOW_MONITOR_HELPER_H + +#include "node-container.h" +#include "ns3/object-factory.h" +#include "ns3/flow-monitor.h" +#include "ns3/flow-classifier.h" +#include + +namespace ns3 { + +class AttributeValue; +class Ipv4FlowClassifier; + +class FlowMonitorHelper +{ +public: + FlowMonitorHelper (); + void SetMonitorAttribute (std::string n1, const AttributeValue &v1); + + Ptr Install (NodeContainer nodes); + Ptr Install (Ptr node); + Ptr InstallAll (); + + Ptr GetMonitor (); + Ptr GetClassifier (); + +private: + ObjectFactory m_monitorFactory; + Ptr m_flowMonitor; + Ptr m_flowClassifier; +}; + +} // namespace ns3 + + +#endif /* FLOW_MONITOR_HELPER_H */ diff --git a/src/helper/wscript b/src/helper/wscript index 3ced3f13a..142d90a46 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -35,6 +35,7 @@ def build(bld): 'ipv6-list-routing-helper.cc', 'ipv6-routing-helper.cc', 'ping6-helper.cc', + 'flow-monitor-helper.cc', ] headers = bld.new_task_gen('ns3header') @@ -72,6 +73,7 @@ def build(bld): 'ipv6-list-routing-helper.h', 'ipv6-routing-helper.h', 'ping6-helper.h', + 'flow-monitor-helper.h', ] env = bld.env_of_name('default') diff --git a/src/wscript b/src/wscript index fcc57038a..27d011b14 100644 --- a/src/wscript +++ b/src/wscript @@ -38,6 +38,7 @@ all_modules = ( 'applications/v4ping', 'applications/ping6', 'applications/radvd', + 'contrib/flow-monitor', ) def set_options(opt): From b4ac818c5126cfacca6853e0bfb493a4f5c0e601 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 31 Aug 2009 18:53:20 +0100 Subject: [PATCH 3/8] Modify example to enable FlowMonitor via command-line option. --- examples/simple-global-routing.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/examples/simple-global-routing.cc b/examples/simple-global-routing.cc index af541d997..edccb69ad 100644 --- a/examples/simple-global-routing.cc +++ b/examples/simple-global-routing.cc @@ -69,6 +69,8 @@ main (int argc, char *argv[]) // Allow the user to override any of the defaults and the above // DefaultValue::Bind ()s at run-time, via command-line arguments CommandLine cmd; + bool enableFlowMonitor = false; + cmd.AddValue("EnableMonitor", "Enable Flow Monitor", enableFlowMonitor); cmd.Parse (argc, argv); // Here, we will explicitly create four nodes. In more sophisticated @@ -148,10 +150,24 @@ main (int argc, char *argv[]) PointToPointHelper::EnablePcapAll ("simple-global-routing"); PointToPointHelper::EnableAsciiAll (ascii); + // Flow Monitor + Ptr flowmon; + if (enableFlowMonitor) + { + FlowMonitorHelper flowmonHelper; + flowmon = flowmonHelper.InstallAll (); + } + NS_LOG_INFO ("Run Simulation."); + Simulator::Stop (Seconds (10)); Simulator::Run (); - Simulator::Destroy (); NS_LOG_INFO ("Done."); + if (enableFlowMonitor) + { + flowmon->SerializeToXmlFile ("simple-global-routing.flowmon", false, false); + } + + Simulator::Destroy (); return 0; } From e29d6c502343e16ae2ddf0befe905b4cd0c21098 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Mon, 31 Aug 2009 18:53:55 +0100 Subject: [PATCH 4/8] Update Python bindings --- bindings/python/ns3_module_core.py | 1 + bindings/python/ns3_module_flow_monitor.py | 406 +++++++++++++++++++ bindings/python/ns3_module_helper.py | 34 ++ bindings/python/ns3_module_internet_stack.py | 2 + bindings/python/ns3modulegen_generated.py | 35 ++ 5 files changed, 478 insertions(+) create mode 100644 bindings/python/ns3_module_flow_monitor.py diff --git a/bindings/python/ns3_module_core.py b/bindings/python/ns3_module_core.py index 835e7c4d1..63803e1fb 100644 --- a/bindings/python/ns3_module_core.py +++ b/bindings/python/ns3_module_core.py @@ -189,6 +189,7 @@ def register_types(module): root_module['ns3::TracedValue< unsigned int >'].implicitly_converts_to(root_module['ns3::EnumValue']) module.add_container('std::list< ns3::Ptr< ns3::RadvdPrefix > >', 'ns3::Ptr< ns3::RadvdPrefix >', container_type='list') module.add_container('std::list< ns3::Ptr< ns3::Packet > >', 'ns3::Ptr< ns3::Packet >', container_type='list') + module.add_container('std::vector< ns3::Ptr< ns3::FlowProbe > >', 'ns3::Ptr< ns3::FlowProbe >', container_type='vector') typehandlers.add_type_alias('ns3::Vector3D', 'ns3::Vector') typehandlers.add_type_alias('ns3::Vector3D*', 'ns3::Vector*') typehandlers.add_type_alias('ns3::Vector3D&', 'ns3::Vector&') diff --git a/bindings/python/ns3_module_flow_monitor.py b/bindings/python/ns3_module_flow_monitor.py new file mode 100644 index 000000000..e5f35473f --- /dev/null +++ b/bindings/python/ns3_module_flow_monitor.py @@ -0,0 +1,406 @@ +from pybindgen import Module, FileCodeSink, param, retval, cppclass, typehandlers + +def register_types(module): + root_module = module.get_root() + + ## histogram.h: ns3::Histogram [class] + module.add_class('Histogram') + ## flow-classifier.h: ns3::FlowClassifier [class] + module.add_class('FlowClassifier', parent=root_module['ns3::RefCountBase']) + ## flow-probe.h: ns3::FlowProbe [class] + module.add_class('FlowProbe', parent=root_module['ns3::RefCountBase']) + ## flow-probe.h: ns3::FlowProbe::FlowStats [struct] + module.add_class('FlowStats', outer_class=root_module['ns3::FlowProbe']) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier [class] + module.add_class('Ipv4FlowClassifier', parent=root_module['ns3::FlowClassifier']) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple [struct] + module.add_class('FiveTuple', outer_class=root_module['ns3::Ipv4FlowClassifier']) + ## ipv4-flow-probe.h: ns3::Ipv4FlowProbe [class] + module.add_class('Ipv4FlowProbe', parent=root_module['ns3::FlowProbe']) + ## ipv4-flow-probe.h: ns3::Ipv4FlowProbe::DropReason [enumeration] + module.add_enum('DropReason', ['DROP_NO_ROUTE', 'DROP_TTL_EXPIRE', 'DROP_BAD_CHECKSUM', 'DROP_INVALID_REASON'], outer_class=root_module['ns3::Ipv4FlowProbe']) + ## flow-monitor.h: ns3::FlowMonitor [class] + module.add_class('FlowMonitor', parent=root_module['ns3::Object']) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats [struct] + module.add_class('FlowStats', outer_class=root_module['ns3::FlowMonitor']) + module.add_container('std::map< unsigned int, ns3::FlowProbe::FlowStats >', ('unsigned int', 'ns3::FlowProbe::FlowStats'), container_type='map') + module.add_container('std::map< unsigned int, ns3::FlowMonitor::FlowStats >', ('unsigned int', 'ns3::FlowMonitor::FlowStats'), container_type='map') + typehandlers.add_type_alias('uint32_t', 'ns3::FlowPacketId') + typehandlers.add_type_alias('uint32_t*', 'ns3::FlowPacketId*') + typehandlers.add_type_alias('uint32_t&', 'ns3::FlowPacketId&') + typehandlers.add_type_alias('uint32_t', 'ns3::FlowId') + typehandlers.add_type_alias('uint32_t*', 'ns3::FlowId*') + typehandlers.add_type_alias('uint32_t&', 'ns3::FlowId&') + + ## Register a nested module for the namespace Config + + nested_module = module.add_cpp_namespace('Config') + register_types_ns3_Config(nested_module) + + + ## Register a nested module for the namespace TimeStepPrecision + + nested_module = module.add_cpp_namespace('TimeStepPrecision') + register_types_ns3_TimeStepPrecision(nested_module) + + + ## Register a nested module for the namespace addressUtils + + nested_module = module.add_cpp_namespace('addressUtils') + register_types_ns3_addressUtils(nested_module) + + + ## Register a nested module for the namespace internal + + nested_module = module.add_cpp_namespace('internal') + register_types_ns3_internal(nested_module) + + + ## Register a nested module for the namespace olsr + + nested_module = module.add_cpp_namespace('olsr') + register_types_ns3_olsr(nested_module) + + +def register_types_ns3_Config(module): + root_module = module.get_root() + + +def register_types_ns3_TimeStepPrecision(module): + root_module = module.get_root() + + +def register_types_ns3_addressUtils(module): + root_module = module.get_root() + + +def register_types_ns3_internal(module): + root_module = module.get_root() + + +def register_types_ns3_olsr(module): + root_module = module.get_root() + + +def register_methods(root_module): + register_Ns3Histogram_methods(root_module, root_module['ns3::Histogram']) + register_Ns3FlowClassifier_methods(root_module, root_module['ns3::FlowClassifier']) + register_Ns3FlowProbe_methods(root_module, root_module['ns3::FlowProbe']) + register_Ns3FlowProbeFlowStats_methods(root_module, root_module['ns3::FlowProbe::FlowStats']) + register_Ns3Ipv4FlowClassifier_methods(root_module, root_module['ns3::Ipv4FlowClassifier']) + register_Ns3Ipv4FlowClassifierFiveTuple_methods(root_module, root_module['ns3::Ipv4FlowClassifier::FiveTuple']) + register_Ns3Ipv4FlowProbe_methods(root_module, root_module['ns3::Ipv4FlowProbe']) + register_Ns3FlowMonitor_methods(root_module, root_module['ns3::FlowMonitor']) + register_Ns3FlowMonitorFlowStats_methods(root_module, root_module['ns3::FlowMonitor::FlowStats']) + return + +def register_Ns3Histogram_methods(root_module, cls): + ## histogram.h: ns3::Histogram::Histogram(ns3::Histogram const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Histogram const &', 'arg0')]) + ## histogram.h: ns3::Histogram::Histogram(double binWidth) [constructor] + cls.add_constructor([param('double', 'binWidth')]) + ## histogram.h: ns3::Histogram::Histogram() [constructor] + cls.add_constructor([]) + ## histogram.h: void ns3::Histogram::AddValue(double value) [member function] + cls.add_method('AddValue', + 'void', + [param('double', 'value')]) + ## histogram.h: uint32_t ns3::Histogram::GetBinCount(uint32_t index) [member function] + cls.add_method('GetBinCount', + 'uint32_t', + [param('uint32_t', 'index')]) + ## histogram.h: double ns3::Histogram::GetBinEnd(uint32_t index) [member function] + cls.add_method('GetBinEnd', + 'double', + [param('uint32_t', 'index')]) + ## histogram.h: double ns3::Histogram::GetBinStart(uint32_t index) [member function] + cls.add_method('GetBinStart', + 'double', + [param('uint32_t', 'index')]) + ## histogram.h: double ns3::Histogram::GetBinWidth(uint32_t index) const [member function] + cls.add_method('GetBinWidth', + 'double', + [param('uint32_t', 'index')], + is_const=True) + ## histogram.h: uint32_t ns3::Histogram::GetNBins() const [member function] + cls.add_method('GetNBins', + 'uint32_t', + [], + is_const=True) + ## histogram.h: void ns3::Histogram::SerializeToXmlStream(std::ostream & os, int indent, std::string elementName) const [member function] + cls.add_method('SerializeToXmlStream', + 'void', + [param('std::ostream &', 'os'), param('int', 'indent'), param('std::string', 'elementName')], + is_const=True) + ## histogram.h: void ns3::Histogram::SetDefaultBinWidth(double binWidth) [member function] + cls.add_method('SetDefaultBinWidth', + 'void', + [param('double', 'binWidth')]) + return + +def register_Ns3FlowClassifier_methods(root_module, cls): + ## flow-classifier.h: ns3::FlowClassifier::FlowClassifier(ns3::FlowClassifier const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowClassifier const &', 'arg0')]) + ## flow-classifier.h: ns3::FlowClassifier::FlowClassifier() [constructor] + cls.add_constructor([]) + ## flow-classifier.h: void ns3::FlowClassifier::SerializeToXmlStream(std::ostream & os, int indent) const [member function] + cls.add_method('SerializeToXmlStream', + 'void', + [param('std::ostream &', 'os'), param('int', 'indent')], + is_pure_virtual=True, is_const=True, is_virtual=True) + ## flow-classifier.h: ns3::FlowId ns3::FlowClassifier::GetNewFlowId() [member function] + cls.add_method('GetNewFlowId', + 'ns3::FlowId', + [], + visibility='protected') + return + +def register_Ns3FlowProbe_methods(root_module, cls): + ## flow-probe.h: ns3::FlowProbe::FlowProbe(ns3::FlowProbe const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowProbe const &', 'arg0')]) + ## flow-probe.h: void ns3::FlowProbe::AddPacketDropStats(ns3::FlowId flowId, uint32_t packetSize, uint32_t reasonCode) [member function] + cls.add_method('AddPacketDropStats', + 'void', + [param('ns3::FlowId', 'flowId'), param('uint32_t', 'packetSize'), param('uint32_t', 'reasonCode')]) + ## flow-probe.h: void ns3::FlowProbe::AddPacketStats(ns3::FlowId flowId, uint32_t packetSize, ns3::Time delayFromFirstProbe) [member function] + cls.add_method('AddPacketStats', + 'void', + [param('ns3::FlowId', 'flowId'), param('uint32_t', 'packetSize'), param('ns3::Time', 'delayFromFirstProbe')]) + ## flow-probe.h: std::map, std::allocator > > ns3::FlowProbe::GetStats() const [member function] + cls.add_method('GetStats', + 'std::map< unsigned int, ns3::FlowProbe::FlowStats >', + [], + is_const=True) + ## flow-probe.h: void ns3::FlowProbe::SerializeToXmlStream(std::ostream & os, int indent, uint32_t index) const [member function] + cls.add_method('SerializeToXmlStream', + 'void', + [param('std::ostream &', 'os'), param('int', 'indent'), param('uint32_t', 'index')], + is_const=True) + ## flow-probe.h: ns3::FlowProbe::FlowProbe(ns3::Ptr flowMonitor) [constructor] + cls.add_constructor([param('ns3::Ptr< ns3::FlowMonitor >', 'flowMonitor')], + visibility='protected') + return + +def register_Ns3FlowProbeFlowStats_methods(root_module, cls): + ## flow-probe.h: ns3::FlowProbe::FlowStats::FlowStats(ns3::FlowProbe::FlowStats const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowProbe::FlowStats const &', 'arg0')]) + ## flow-probe.h: ns3::FlowProbe::FlowStats::FlowStats() [constructor] + cls.add_constructor([]) + ## flow-probe.h: ns3::FlowProbe::FlowStats::bytes [variable] + cls.add_instance_attribute('bytes', 'uint64_t', is_const=False) + ## flow-probe.h: ns3::FlowProbe::FlowStats::bytesDropped [variable] + cls.add_instance_attribute('bytesDropped', 'std::vector< unsigned long >', is_const=False) + ## flow-probe.h: ns3::FlowProbe::FlowStats::delayFromFirstProbeSum [variable] + cls.add_instance_attribute('delayFromFirstProbeSum', 'ns3::Time', is_const=False) + ## flow-probe.h: ns3::FlowProbe::FlowStats::packets [variable] + cls.add_instance_attribute('packets', 'uint32_t', is_const=False) + ## flow-probe.h: ns3::FlowProbe::FlowStats::packetsDropped [variable] + cls.add_instance_attribute('packetsDropped', 'std::vector< unsigned int >', is_const=False) + return + +def register_Ns3Ipv4FlowClassifier_methods(root_module, cls): + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::Ipv4FlowClassifier(ns3::Ipv4FlowClassifier const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Ipv4FlowClassifier const &', 'arg0')]) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::Ipv4FlowClassifier() [constructor] + cls.add_constructor([]) + ## ipv4-flow-classifier.h: bool ns3::Ipv4FlowClassifier::Classify(ns3::Ipv4Header const & ipHeader, ns3::Ptr ipPayload, uint32_t * out_flowId, uint32_t * out_packetId) [member function] + cls.add_method('Classify', + 'bool', + [param('ns3::Ipv4Header const &', 'ipHeader'), param('ns3::Ptr< ns3::Packet const >', 'ipPayload'), param('uint32_t *', 'out_flowId'), param('uint32_t *', 'out_packetId')]) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple ns3::Ipv4FlowClassifier::FindFlow(ns3::FlowId flowId) const [member function] + cls.add_method('FindFlow', + 'ns3::Ipv4FlowClassifier::FiveTuple', + [param('ns3::FlowId', 'flowId')], + is_const=True) + ## ipv4-flow-classifier.h: void ns3::Ipv4FlowClassifier::SerializeToXmlStream(std::ostream & os, int indent) const [member function] + cls.add_method('SerializeToXmlStream', + 'void', + [param('std::ostream &', 'os'), param('int', 'indent')], + is_const=True, is_virtual=True) + return + +def register_Ns3Ipv4FlowClassifierFiveTuple_methods(root_module, cls): + cls.add_binary_comparison_operator('<') + cls.add_binary_comparison_operator('==') + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::FiveTuple() [constructor] + cls.add_constructor([]) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::FiveTuple(ns3::Ipv4FlowClassifier::FiveTuple const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Ipv4FlowClassifier::FiveTuple const &', 'arg0')]) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::destinationAddress [variable] + cls.add_instance_attribute('destinationAddress', 'ns3::Ipv4Address', is_const=False) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::destinationPort [variable] + cls.add_instance_attribute('destinationPort', 'uint16_t', is_const=False) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::protocol [variable] + cls.add_instance_attribute('protocol', 'uint8_t', is_const=False) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::sourceAddress [variable] + cls.add_instance_attribute('sourceAddress', 'ns3::Ipv4Address', is_const=False) + ## ipv4-flow-classifier.h: ns3::Ipv4FlowClassifier::FiveTuple::sourcePort [variable] + cls.add_instance_attribute('sourcePort', 'uint16_t', is_const=False) + return + +def register_Ns3Ipv4FlowProbe_methods(root_module, cls): + ## ipv4-flow-probe.h: ns3::Ipv4FlowProbe::Ipv4FlowProbe(ns3::Ipv4FlowProbe const & arg0) [copy constructor] + cls.add_constructor([param('ns3::Ipv4FlowProbe const &', 'arg0')]) + ## ipv4-flow-probe.h: ns3::Ipv4FlowProbe::Ipv4FlowProbe(ns3::Ptr monitor, ns3::Ptr classifier, ns3::Ptr node) [constructor] + cls.add_constructor([param('ns3::Ptr< ns3::FlowMonitor >', 'monitor'), param('ns3::Ptr< ns3::Ipv4FlowClassifier >', 'classifier'), param('ns3::Ptr< ns3::Node >', 'node')]) + return + +def register_Ns3FlowMonitor_methods(root_module, cls): + ## flow-monitor.h: ns3::FlowMonitor::FlowMonitor(ns3::FlowMonitor const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowMonitor const &', 'arg0')]) + ## flow-monitor.h: ns3::FlowMonitor::FlowMonitor() [constructor] + cls.add_constructor([]) + ## flow-monitor.h: void ns3::FlowMonitor::AddProbe(ns3::Ptr probe) [member function] + cls.add_method('AddProbe', + 'void', + [param('ns3::Ptr< ns3::FlowProbe >', 'probe')]) + ## flow-monitor.h: void ns3::FlowMonitor::CheckForLostPackets() [member function] + cls.add_method('CheckForLostPackets', + 'void', + []) + ## flow-monitor.h: void ns3::FlowMonitor::CheckForLostPackets(ns3::Time maxDelay) [member function] + cls.add_method('CheckForLostPackets', + 'void', + [param('ns3::Time', 'maxDelay')]) + ## flow-monitor.h: std::vector, std::allocator > > ns3::FlowMonitor::GetAllProbes() const [member function] + cls.add_method('GetAllProbes', + 'std::vector< ns3::Ptr< ns3::FlowProbe > >', + [], + is_const=True) + ## flow-monitor.h: std::map, std::allocator > > ns3::FlowMonitor::GetFlowStats() const [member function] + cls.add_method('GetFlowStats', + 'std::map< unsigned int, ns3::FlowMonitor::FlowStats >', + [], + is_const=True) + ## flow-monitor.h: ns3::TypeId ns3::FlowMonitor::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## flow-monitor.h: static ns3::TypeId ns3::FlowMonitor::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## flow-monitor.h: void ns3::FlowMonitor::ReportDrop(ns3::Ptr probe, ns3::FlowId flowId, ns3::FlowPacketId packetId, uint32_t packetSize, uint32_t reasonCode) [member function] + cls.add_method('ReportDrop', + 'void', + [param('ns3::Ptr< ns3::FlowProbe >', 'probe'), param('ns3::FlowId', 'flowId'), param('ns3::FlowPacketId', 'packetId'), param('uint32_t', 'packetSize'), param('uint32_t', 'reasonCode')]) + ## flow-monitor.h: void ns3::FlowMonitor::ReportFirstTx(ns3::Ptr probe, ns3::FlowId flowId, ns3::FlowPacketId packetId, uint32_t packetSize) [member function] + cls.add_method('ReportFirstTx', + 'void', + [param('ns3::Ptr< ns3::FlowProbe >', 'probe'), param('ns3::FlowId', 'flowId'), param('ns3::FlowPacketId', 'packetId'), param('uint32_t', 'packetSize')]) + ## flow-monitor.h: void ns3::FlowMonitor::ReportForwarding(ns3::Ptr probe, ns3::FlowId flowId, ns3::FlowPacketId packetId, uint32_t packetSize) [member function] + cls.add_method('ReportForwarding', + 'void', + [param('ns3::Ptr< ns3::FlowProbe >', 'probe'), param('ns3::FlowId', 'flowId'), param('ns3::FlowPacketId', 'packetId'), param('uint32_t', 'packetSize')]) + ## flow-monitor.h: void ns3::FlowMonitor::ReportLastRx(ns3::Ptr probe, ns3::FlowId flowId, ns3::FlowPacketId packetId, uint32_t packetSize) [member function] + cls.add_method('ReportLastRx', + 'void', + [param('ns3::Ptr< ns3::FlowProbe >', 'probe'), param('ns3::FlowId', 'flowId'), param('ns3::FlowPacketId', 'packetId'), param('uint32_t', 'packetSize')]) + ## flow-monitor.h: void ns3::FlowMonitor::SerializeToXmlFile(std::string fileName, bool enableHistograms, bool enableProbes) [member function] + cls.add_method('SerializeToXmlFile', + 'void', + [param('std::string', 'fileName'), param('bool', 'enableHistograms'), param('bool', 'enableProbes')]) + ## flow-monitor.h: void ns3::FlowMonitor::SerializeToXmlStream(std::ostream & os, int indent, bool enableHistograms, bool enableProbes) [member function] + cls.add_method('SerializeToXmlStream', + 'void', + [param('std::ostream &', 'os'), param('int', 'indent'), param('bool', 'enableHistograms'), param('bool', 'enableProbes')]) + ## flow-monitor.h: std::string ns3::FlowMonitor::SerializeToXmlString(int indent, bool enableHistograms, bool enableProbes) [member function] + cls.add_method('SerializeToXmlString', + 'std::string', + [param('int', 'indent'), param('bool', 'enableHistograms'), param('bool', 'enableProbes')]) + ## flow-monitor.h: void ns3::FlowMonitor::SetFlowClassifier(ns3::Ptr classifier) [member function] + cls.add_method('SetFlowClassifier', + 'void', + [param('ns3::Ptr< ns3::FlowClassifier >', 'classifier')]) + ## flow-monitor.h: void ns3::FlowMonitor::Start(ns3::Time const & time) [member function] + cls.add_method('Start', + 'void', + [param('ns3::Time const &', 'time')]) + ## flow-monitor.h: void ns3::FlowMonitor::StartRightNow() [member function] + cls.add_method('StartRightNow', + 'void', + []) + ## flow-monitor.h: void ns3::FlowMonitor::Stop(ns3::Time const & time) [member function] + cls.add_method('Stop', + 'void', + [param('ns3::Time const &', 'time')]) + ## flow-monitor.h: void ns3::FlowMonitor::StopRightNow() [member function] + cls.add_method('StopRightNow', + 'void', + []) + ## flow-monitor.h: void ns3::FlowMonitor::NotifyConstructionCompleted() [member function] + cls.add_method('NotifyConstructionCompleted', + 'void', + [], + visibility='protected', is_virtual=True) + return + +def register_Ns3FlowMonitorFlowStats_methods(root_module, cls): + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::FlowStats() [constructor] + cls.add_constructor([]) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::FlowStats(ns3::FlowMonitor::FlowStats const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowMonitor::FlowStats const &', 'arg0')]) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::bytesDropped [variable] + cls.add_instance_attribute('bytesDropped', 'std::vector< unsigned long >', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::delayHistogram [variable] + cls.add_instance_attribute('delayHistogram', 'ns3::Histogram', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::delaySum [variable] + cls.add_instance_attribute('delaySum', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::jitterHistogram [variable] + cls.add_instance_attribute('jitterHistogram', 'ns3::Histogram', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::jitterSum [variable] + cls.add_instance_attribute('jitterSum', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::lastDelay [variable] + cls.add_instance_attribute('lastDelay', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::lostPackets [variable] + cls.add_instance_attribute('lostPackets', 'uint32_t', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::packetSizeHistogram [variable] + cls.add_instance_attribute('packetSizeHistogram', 'ns3::Histogram', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::packetsDropped [variable] + cls.add_instance_attribute('packetsDropped', 'std::vector< unsigned int >', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::rxBytes [variable] + cls.add_instance_attribute('rxBytes', 'uint64_t', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::rxPackets [variable] + cls.add_instance_attribute('rxPackets', 'uint32_t', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::timeFirstRxPacket [variable] + cls.add_instance_attribute('timeFirstRxPacket', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::timeFirstTxPacket [variable] + cls.add_instance_attribute('timeFirstTxPacket', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::timeLastRxPacket [variable] + cls.add_instance_attribute('timeLastRxPacket', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::timeLastTxPacket [variable] + cls.add_instance_attribute('timeLastTxPacket', 'ns3::Time', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::timesForwarded [variable] + cls.add_instance_attribute('timesForwarded', 'uint32_t', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::txBytes [variable] + cls.add_instance_attribute('txBytes', 'uint64_t', is_const=False) + ## flow-monitor.h: ns3::FlowMonitor::FlowStats::txPackets [variable] + cls.add_instance_attribute('txPackets', 'uint32_t', is_const=False) + return + +def register_functions(root_module): + module = root_module + register_functions_ns3_Config(module.get_submodule('Config'), root_module) + register_functions_ns3_TimeStepPrecision(module.get_submodule('TimeStepPrecision'), root_module) + register_functions_ns3_addressUtils(module.get_submodule('addressUtils'), root_module) + register_functions_ns3_internal(module.get_submodule('internal'), root_module) + register_functions_ns3_olsr(module.get_submodule('olsr'), root_module) + return + +def register_functions_ns3_Config(module, root_module): + return + +def register_functions_ns3_TimeStepPrecision(module, root_module): + return + +def register_functions_ns3_addressUtils(module, root_module): + return + +def register_functions_ns3_internal(module, root_module): + return + +def register_functions_ns3_olsr(module, root_module): + return + diff --git a/bindings/python/ns3_module_helper.py b/bindings/python/ns3_module_helper.py index b997f67e8..239efad02 100644 --- a/bindings/python/ns3_module_helper.py +++ b/bindings/python/ns3_module_helper.py @@ -13,6 +13,8 @@ def register_types(module): module.add_class('CsmaHelper', allow_subclassing=False) ## emu-helper.h: ns3::EmuHelper [class] module.add_class('EmuHelper', allow_subclassing=False) + ## flow-monitor-helper.h: ns3::FlowMonitorHelper [class] + module.add_class('FlowMonitorHelper', allow_subclassing=False) ## internet-stack-helper.h: ns3::InternetStackHelper [class] module.add_class('InternetStackHelper', allow_subclassing=False) ## ipv4-address-helper.h: ns3::Ipv4AddressHelper [class] @@ -140,6 +142,7 @@ def register_methods(root_module): register_Ns3BridgeHelper_methods(root_module, root_module['ns3::BridgeHelper']) register_Ns3CsmaHelper_methods(root_module, root_module['ns3::CsmaHelper']) register_Ns3EmuHelper_methods(root_module, root_module['ns3::EmuHelper']) + register_Ns3FlowMonitorHelper_methods(root_module, root_module['ns3::FlowMonitorHelper']) register_Ns3InternetStackHelper_methods(root_module, root_module['ns3::InternetStackHelper']) register_Ns3Ipv4AddressHelper_methods(root_module, root_module['ns3::Ipv4AddressHelper']) register_Ns3Ipv4InterfaceContainer_methods(root_module, root_module['ns3::Ipv4InterfaceContainer']) @@ -471,6 +474,37 @@ def register_Ns3EmuHelper_methods(root_module, cls): [param('std::string', 'type'), param('std::string', 'n1', default_value='""'), param('ns3::AttributeValue const &', 'v1', default_value='ns3::EmptyAttributeValue()'), param('std::string', 'n2', default_value='""'), param('ns3::AttributeValue const &', 'v2', default_value='ns3::EmptyAttributeValue()'), param('std::string', 'n3', default_value='""'), param('ns3::AttributeValue const &', 'v3', default_value='ns3::EmptyAttributeValue()'), param('std::string', 'n4', default_value='""'), param('ns3::AttributeValue const &', 'v4', default_value='ns3::EmptyAttributeValue()')]) return +def register_Ns3FlowMonitorHelper_methods(root_module, cls): + ## flow-monitor-helper.h: ns3::FlowMonitorHelper::FlowMonitorHelper(ns3::FlowMonitorHelper const & arg0) [copy constructor] + cls.add_constructor([param('ns3::FlowMonitorHelper const &', 'arg0')]) + ## flow-monitor-helper.h: ns3::FlowMonitorHelper::FlowMonitorHelper() [constructor] + cls.add_constructor([]) + ## flow-monitor-helper.h: ns3::Ptr ns3::FlowMonitorHelper::GetClassifier() [member function] + cls.add_method('GetClassifier', + 'ns3::Ptr< ns3::FlowClassifier >', + []) + ## flow-monitor-helper.h: ns3::Ptr ns3::FlowMonitorHelper::GetMonitor() [member function] + cls.add_method('GetMonitor', + 'ns3::Ptr< ns3::FlowMonitor >', + []) + ## flow-monitor-helper.h: ns3::Ptr ns3::FlowMonitorHelper::Install(ns3::NodeContainer nodes) [member function] + cls.add_method('Install', + 'ns3::Ptr< ns3::FlowMonitor >', + [param('ns3::NodeContainer', 'nodes')]) + ## flow-monitor-helper.h: ns3::Ptr ns3::FlowMonitorHelper::Install(ns3::Ptr node) [member function] + cls.add_method('Install', + 'ns3::Ptr< ns3::FlowMonitor >', + [param('ns3::Ptr< ns3::Node >', 'node')]) + ## flow-monitor-helper.h: ns3::Ptr ns3::FlowMonitorHelper::InstallAll() [member function] + cls.add_method('InstallAll', + 'ns3::Ptr< ns3::FlowMonitor >', + []) + ## flow-monitor-helper.h: void ns3::FlowMonitorHelper::SetMonitorAttribute(std::string n1, ns3::AttributeValue const & v1) [member function] + cls.add_method('SetMonitorAttribute', + 'void', + [param('std::string', 'n1'), param('ns3::AttributeValue const &', 'v1')]) + return + def register_Ns3InternetStackHelper_methods(root_module, cls): ## internet-stack-helper.h: ns3::InternetStackHelper::InternetStackHelper(ns3::InternetStackHelper const & arg0) [copy constructor] cls.add_constructor([param('ns3::InternetStackHelper const &', 'arg0')]) diff --git a/bindings/python/ns3_module_internet_stack.py b/bindings/python/ns3_module_internet_stack.py index df38c1743..8c2f53656 100644 --- a/bindings/python/ns3_module_internet_stack.py +++ b/bindings/python/ns3_module_internet_stack.py @@ -73,6 +73,8 @@ def register_types(module): module.add_class('Icmpv6Echo', parent=root_module['ns3::Icmpv6Header']) ## ipv4-l3-protocol.h: ns3::Ipv4L3Protocol [class] module.add_class('Ipv4L3Protocol', parent=root_module['ns3::Ipv4']) + ## ipv4-l3-protocol.h: ns3::Ipv4L3Protocol::DropReason [enumeration] + module.add_enum('DropReason', ['DROP_TTL_EXPIRED', 'DROP_NO_ROUTE', 'DROP_BAD_CHECKSUM', 'DROP_INTERFACE_DOWN', 'DROP_ROUTE_ERROR'], outer_class=root_module['ns3::Ipv4L3Protocol']) ## ipv4-l4-protocol.h: ns3::Ipv4L4Protocol [class] module.add_class('Ipv4L4Protocol', parent=root_module['ns3::Object']) ## ipv4-l4-protocol.h: ns3::Ipv4L4Protocol::RxStatus [enumeration] diff --git a/bindings/python/ns3modulegen_generated.py b/bindings/python/ns3modulegen_generated.py index 93400d54f..037979b55 100644 --- a/bindings/python/ns3modulegen_generated.py +++ b/bindings/python/ns3modulegen_generated.py @@ -37,6 +37,7 @@ import ns3_module_udp_echo import ns3_module_olsr import ns3_module_radvd import ns3_module_ping6 +import ns3_module_flow_monitor import ns3_module_helper def module_init(): @@ -321,6 +322,17 @@ def register_types(module): ns3_module_ping6__local.register_types(module) root_module.end_section('ns3_module_ping6') + root_module.begin_section('ns3_module_flow_monitor') + ns3_module_flow_monitor.register_types(module) + + try: + import ns3_module_flow_monitor__local + except ImportError: + pass + else: + ns3_module_flow_monitor__local.register_types(module) + + root_module.end_section('ns3_module_flow_monitor') root_module.begin_section('ns3_module_helper') ns3_module_helper.register_types(module) @@ -334,6 +346,7 @@ def register_types(module): root_module.end_section('ns3_module_helper') module.add_container('std::vector< unsigned int >', 'unsigned int', container_type='vector') module.add_container('std::vector< bool >', 'bool', container_type='vector') + module.add_container('std::vector< unsigned long >', 'long unsigned int', container_type='vector') module.add_container('std::list< unsigned int >', 'unsigned int', container_type='list') module.add_container('std::list< std::pair< ns3::Ptr< ns3::Packet >, ns3::AmsduSubframeHeader > >', 'std::pair< ns3::Ptr< ns3::Packet >, ns3::AmsduSubframeHeader >', container_type='list') @@ -664,6 +677,17 @@ def register_methods(root_module): ns3_module_ping6__local.register_methods(root_module) root_module.end_section('ns3_module_ping6') + root_module.begin_section('ns3_module_flow_monitor') + ns3_module_flow_monitor.register_methods(root_module) + + try: + import ns3_module_flow_monitor__local + except ImportError: + pass + else: + ns3_module_flow_monitor__local.register_methods(root_module) + + root_module.end_section('ns3_module_flow_monitor') root_module.begin_section('ns3_module_helper') ns3_module_helper.register_methods(root_module) @@ -954,6 +978,17 @@ def register_functions(root_module): ns3_module_ping6__local.register_functions(root_module) root_module.end_section('ns3_module_ping6') + root_module.begin_section('ns3_module_flow_monitor') + ns3_module_flow_monitor.register_functions(root_module) + + try: + import ns3_module_flow_monitor__local + except ImportError: + pass + else: + ns3_module_flow_monitor__local.register_functions(root_module) + + root_module.end_section('ns3_module_flow_monitor') root_module.begin_section('ns3_module_helper') ns3_module_helper.register_functions(root_module) From 796e3d17d88a58b8d5d02b6a7cf2166e28314c5d Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 8 Sep 2009 17:33:05 +0100 Subject: [PATCH 5/8] Doxygen documentation for FlowMonitor --- src/contrib/flow-monitor/flow-classifier.h | 11 +- src/contrib/flow-monitor/flow-monitor.h | 116 +++++++++++++++++- src/contrib/flow-monitor/flow-probe.h | 21 +++- .../flow-monitor/ipv4-flow-classifier.h | 6 +- src/contrib/flow-monitor/ipv4-flow-probe.h | 13 +- src/helper/flow-monitor-helper.h | 10 ++ 6 files changed, 165 insertions(+), 12 deletions(-) diff --git a/src/contrib/flow-monitor/flow-classifier.h b/src/contrib/flow-monitor/flow-classifier.h index 0029ef771..fca1c865c 100644 --- a/src/contrib/flow-monitor/flow-classifier.h +++ b/src/contrib/flow-monitor/flow-classifier.h @@ -29,7 +29,16 @@ namespace ns3 { typedef uint32_t FlowId; typedef uint32_t FlowPacketId; - +/// provides a method to translate raw packet data into abstract +/// ``flow identifier'' and ``packet identifier'' parameters. These +/// identifiers are unsigned 32-bit integers that uniquely identify a +/// flow and a packet within that flow, respectively, for the whole +/// simulation, regardless of the point in which the packet was +/// captured. These abstract identifiers are used in the +/// communication between FlowProbe and FlowMonitor, and all collected +/// statistics reference only those abstract identifiers in order to +/// keep the core architecture generic and not tied down to any +/// particular flow capture method or classification system. class FlowClassifier : public RefCountBase { FlowId m_lastNewFlowId; diff --git a/src/contrib/flow-monitor/flow-monitor.h b/src/contrib/flow-monitor/flow-monitor.h index d1acc8fcc..7f8096219 100644 --- a/src/contrib/flow-monitor/flow-monitor.h +++ b/src/contrib/flow-monitor/flow-monitor.h @@ -34,30 +34,94 @@ namespace ns3 { - +/// \brief An object that monitors and reports back packet flows observed during a simulation +/// +/// The FlowMonitor class is responsible forcoordinating efforts +/// regarding probes, and collects end-to-end flowstatistics. class FlowMonitor : public Object { public: + /// \brief Structure that represents the measured metrics of an individual packet flow struct FlowStats { + /// Contains the absolute time when the first packet in the flow + /// was transmitted, i.e. the time when the flow transmission + /// starts Time timeFirstTxPacket; + + /// Contains the absolute time when the first packet in the flow + /// was received by an end node, i.e. the time when the flow + /// reception starts Time timeFirstRxPacket; + + /// Contains the absolute time when the last packet in the flow + /// was transmitted, i.e. the time when the flow transmission + /// ends Time timeLastTxPacket; + + /// Contains the absolute time when the last packet in the flow + /// was received, i.e. the time when the flow reception ends Time timeLastRxPacket; + + /// Contains the sum of all end-to-end delays for all received + /// packets of the flow. Time delaySum; // delayCount == rxPackets + + /// Contains the sum of all end-to-end delay jitter (delay + /// variation) values for all received packets of the flow. Here + /// we define _jitter_ of a packet as the delay variation + /// relatively to the last packet of the stream, + /// i.e. \f$Jitter\left\{P_N\right\} = \left|Delay\left\{P_N\right\} - Delay\left\{P_{N-1}\right\}\right|\f$. + /// This definition is in accordance with the Type-P-One-way-ipdv + /// as defined in IETF RFC 3393. Time jitterSum; // jitterCount == rxPackets - 1 + Time lastDelay; + + /// Total number of transmitted bytes for the flow uint64_t txBytes; + /// Total number of received bytes for the flow uint64_t rxBytes; + /// Total number of transmitted packets for the flow uint32_t txPackets; + /// Total number of received packets for the flow uint32_t rxPackets; + + /// Total number of packets that are assumed to be lost, + /// i.e. those that were transmitted but have not been reportedly + /// received or forwarded for a long time. By default, packets + /// missing for a period of over 10 seconds are assumed to be + /// lost, although this value can be easily configured in runtime uint32_t lostPackets; - uint32_t timesForwarded; // number of times a packet was forwarded, summed for all received packets + + /// Contains the number of times a packet has been reportedly + /// forwarded, summed for all received packets in the flow + uint32_t timesForwarded; + + /// Histogram of the packet delays Histogram delayHistogram; + /// Histogram of the packet jitters Histogram jitterHistogram; + /// Histogram of the packet sizes Histogram packetSizeHistogram; + + /// This attribute also tracks the number of lost packets and + /// bytes, but discriminates the losses by a _reason code_. This + /// reason code is usually an enumeration defined by the concrete + /// FlowProbe class, and for each reason code there may be a + /// vector entry indexed by that code and whose value is the + /// number of packets or bytes lost due to this reason. For + /// instance, in the Ipv4FlowProbe case the following reasons are + /// currently defined: DROP_NO_ROUTE (no IPv4 route found for a + /// packet), DROP_TTL_EXPIRE (a packet was dropped due to an IPv4 + /// TTL field decremented and reaching zero), and + /// DROP_BAD_CHECKSUM (a packet had bad IPv4 header checksum and + /// had to be dropped). std::vector packetsDropped; // packetsDropped[reasonCode] => number of dropped packets + + /// This attribute also tracks the number of lost bytes. See also + /// comment in attribute packetsDropped. std::vector bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes }; @@ -65,33 +129,75 @@ public: static TypeId GetTypeId (); TypeId GetInstanceTypeId () const; FlowMonitor (); - void SetFlowClassifier (Ptr classifier); + /// Set the FlowClassifier to be used by the flow monitor. + void SetFlowClassifier (Ptr classifier); + + /// Set the time, counting from the current time, from which to start monitoring flows void Start (const Time &time); + /// Set the time, counting from the current time, from which to stop monitoring flows void Stop (const Time &time); + /// Begin monitoring flows *right now* void StartRightNow (); + /// End monitoring flows *right now* void StopRightNow (); // --- methods to be used by the FlowMonitorProbe's only --- + /// Register a new FlowProbe that will begin monitoring and report + /// events to this monitor. This method is normally only used by + /// FlowProbe implementations. void AddProbe (Ptr probe); + + /// FlowProbe implementations are supposed to call this method to + /// report that a new packet was transmitted (but keep in mind the + /// distinction between a new packet entering the system and a + /// packet that is already known and is only being forwarded). void ReportFirstTx (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + /// FlowProbe implementations are supposed to call this method to + /// report that a known packet is being forwarded. void ReportForwarding (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + /// FlowProbe implementations are supposed to call this method to + /// report that a known packet is being received. void ReportLastRx (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize); + /// FlowProbe implementations are supposed to call this method to + /// report that a known packet is being dropped due to some reason. void ReportDrop (Ptr probe, FlowId flowId, FlowPacketId packetId, uint32_t packetSize, uint32_t reasonCode); - /// Check right now for packets that appear to be lost void CheckForLostPackets (); + + /// Check right now for packets that appear to be lost, considering + /// packets as lost if not seen in the network for a time larger + /// than maxDelay void CheckForLostPackets (Time maxDelay); // --- methods to get the results --- - // remember to call CheckForLostPackets first! + /// Retrieve all collected the flow statistics. Note, if the + /// FlowMonitor has not stopped monitoring yet, you should call + /// CheckForLostPackets() to make sure all possibly lost packets are + /// accounted for. std::map GetFlowStats () const; + + /// Get a list of all FlowProbe's associated with this FlowMonitor std::vector< Ptr > GetAllProbes () const; + /// Serializes the results to an std::ostream in XML format + /// \param os the output stream + /// \param indent number of spaces to use as base indentation level + /// \param enableHistograms if true, include also the histograms in the output + /// \param enableProbes if true, include also the per-probe/flow pair statistics in the output void SerializeToXmlStream (std::ostream &os, int indent, bool enableHistograms, bool enableProbes); + /// Same as SerializeToXmlStream, but returns the output as a std::string + /// \param indent number of spaces to use as base indentation level + /// \param enableHistograms if true, include also the histograms in the output + /// \param enableProbes if true, include also the per-probe/flow pair statistics in the output + /// \return the XML output as string std::string SerializeToXmlString (int indent, bool enableHistograms, bool enableProbes); + /// Same as SerializeToXmlStream, but writes to a file instead + /// \param fileName name or path of the output file that will be created + /// \param enableHistograms if true, include also the histograms in the output + /// \param enableProbes if true, include also the per-probe/flow pair statistics in the output void SerializeToXmlFile (std::string fileName, bool enableHistograms, bool enableProbes); diff --git a/src/contrib/flow-monitor/flow-probe.h b/src/contrib/flow-monitor/flow-probe.h index 3b86f16b7..f5857a0e6 100644 --- a/src/contrib/flow-monitor/flow-probe.h +++ b/src/contrib/flow-monitor/flow-probe.h @@ -32,7 +32,10 @@ namespace ns3 { class FlowMonitor; - +/// The FlowProbe class is responsible for listening for packet events +/// in a specific point of the simulated space, report those events to +/// the global FlowMonitor, and collect its own flow statistics +/// regarding only the packets that pass through that probe. class FlowProbe : public RefCountBase { protected: @@ -46,10 +49,16 @@ public: { FlowStats () : delayFromFirstProbeSum (Seconds (0)), bytes (0), packets (0) {} - std::vector packetsDropped; // packetsDropped[reasonCode] => number of dropped packets - std::vector bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes - Time delayFromFirstProbeSum; // divide by 'Scalar (packets)' to get the average delay + /// packetsDropped[reasonCode] => number of dropped packets + std::vector packetsDropped; + /// bytesDropped[reasonCode] => number of dropped bytes + std::vector bytesDropped; + /// divide by 'Scalar (packets)' to get the average delay from the + /// first (entry) probe up to this one (partial delay) + Time delayFromFirstProbeSum; + /// Number of bytes seen of this flow uint64_t bytes; + /// Number of packets seen of this flow uint32_t packets; }; @@ -57,6 +66,10 @@ public: void AddPacketStats (FlowId flowId, uint32_t packetSize, Time delayFromFirstProbe); void AddPacketDropStats (FlowId flowId, uint32_t packetSize, uint32_t reasonCode); + + /// Get the partial flow statistics stored in this probe. With this + /// information you can, for example, find out what is the delay + /// from the first probe to this one. Stats GetStats () const; void SerializeToXmlStream (std::ostream &os, int indent, uint32_t index) const; diff --git a/src/contrib/flow-monitor/ipv4-flow-classifier.h b/src/contrib/flow-monitor/ipv4-flow-classifier.h index fff4baa71..5dca4c59e 100644 --- a/src/contrib/flow-monitor/ipv4-flow-classifier.h +++ b/src/contrib/flow-monitor/ipv4-flow-classifier.h @@ -30,7 +30,11 @@ namespace ns3 { class Packet; - + +/// Classifies packets by looking at their IP and TCP/UDP headers. +/// From these packet headers, a tuple (source-ip, destination-ip, +/// protocol, source-port, destination-port) is created, and a unique +/// flow identifier is assigned for each different tuple combination class Ipv4FlowClassifier : public FlowClassifier { public: diff --git a/src/contrib/flow-monitor/ipv4-flow-probe.h b/src/contrib/flow-monitor/ipv4-flow-probe.h index 4248f771e..686516002 100644 --- a/src/contrib/flow-monitor/ipv4-flow-probe.h +++ b/src/contrib/flow-monitor/ipv4-flow-probe.h @@ -30,6 +30,12 @@ namespace ns3 { class FlowMonitor; class Node; +/// \brief Class that monitors flows at the IPv4 layer of a Node +/// +/// For each node in the simulation, one instance of the class +/// Ipv4FlowProbe is created to monitor that node. Ipv4FlowProbe +/// accomplishes this by connecting callbacks to trace sources in the +/// Ipv4L3Protocol interface of the node. class Ipv4FlowProbe : public FlowProbe { @@ -37,11 +43,16 @@ public: Ipv4FlowProbe (Ptr monitor, Ptr classifier, Ptr node); ~Ipv4FlowProbe (); + /// \brief enumeration of possible reasons why a packet may be dropped enum DropReason { + /// Packet dropped due to missing route to the destination DROP_NO_ROUTE = 0, - DROP_TTL_EXPIRE, + /// 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 DROP_INVALID_REASON, }; diff --git a/src/helper/flow-monitor-helper.h b/src/helper/flow-monitor-helper.h index bdd4e99ac..1b5ed2d68 100644 --- a/src/helper/flow-monitor-helper.h +++ b/src/helper/flow-monitor-helper.h @@ -31,17 +31,27 @@ namespace ns3 { class AttributeValue; class Ipv4FlowClassifier; +/// \brief Helper to enable IPv4 flow monitoring on a set of Nodes class FlowMonitorHelper { public: FlowMonitorHelper (); + + + /// \brief Set an attribute for the to-be-created FlowMonitor object void SetMonitorAttribute (std::string n1, const AttributeValue &v1); + /// \brief Enable flow monitoring on a set of nodes Ptr Install (NodeContainer nodes); + /// \brief Enable flow monitoring on a single node Ptr Install (Ptr node); + /// \brief Enable flow monitoring on all nodes Ptr InstallAll (); + /// \brief Retrieve the FlowMonitor object created by the Install* methods Ptr GetMonitor (); + + /// \brief Retrieve the FlowClassifier object created by the Install* methods Ptr GetClassifier (); private: From fe07997f95a29b40619f858b7f5db6f147bfbe1c Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 15 Sep 2009 12:58:31 +0100 Subject: [PATCH 6/8] Fix the example stop time to make regression tests pass again --- examples/simple-global-routing.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple-global-routing.cc b/examples/simple-global-routing.cc index edccb69ad..a75fa6111 100644 --- a/examples/simple-global-routing.cc +++ b/examples/simple-global-routing.cc @@ -159,7 +159,7 @@ main (int argc, char *argv[]) } NS_LOG_INFO ("Run Simulation."); - Simulator::Stop (Seconds (10)); + Simulator::Stop (Seconds (11)); Simulator::Run (); NS_LOG_INFO ("Done."); From a4036e14fb593b293c7ae44a924cb8c374942154 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 15 Sep 2009 13:00:29 +0100 Subject: [PATCH 7/8] Modifications to the Ipv6L3Protocol::Drop trace source to align with Ipv4L3Protocol::Drop --- src/internet-stack/ipv6-l3-protocol.cc | 26 ++++++++++++++------------ src/internet-stack/ipv6-l3-protocol.h | 11 ++++++++++- src/internet-stack/wscript | 1 + 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/internet-stack/ipv6-l3-protocol.cc b/src/internet-stack/ipv6-l3-protocol.cc index 1bdf10012..7be86e33d 100644 --- a/src/internet-stack/ipv6-l3-protocol.cc +++ b/src/internet-stack/ipv6-l3-protocol.cc @@ -646,7 +646,7 @@ void Ipv6L3Protocol::Send (Ptr packet, Ipv6Address source, Ipv6Address d else { NS_LOG_WARN ("No route to host, drop!"); - m_dropTrace (packet); + m_dropTrace (hdr, packet, DROP_NO_ROUTE, oif); } } @@ -672,7 +672,9 @@ void Ipv6L3Protocol::Receive (Ptr device, Ptr p, uint16 else { NS_LOG_LOGIC ("Dropping received packet-- interface is down"); - m_dropTrace (packet); + Ipv6Header hdr; + packet->RemoveHeader (hdr); + m_dropTrace (hdr, packet, DROP_INTERFACE_DOWN, interface); return; } } @@ -701,8 +703,6 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 { NS_LOG_FUNCTION (this << route << packet << ipHeader); - packet->AddHeader (ipHeader); - if (!route) { NS_LOG_LOGIC ("No route to host, drop!."); @@ -716,20 +716,20 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 Ptr outInterface = GetInterface (interface); NS_LOG_LOGIC ("Send via NetDevice ifIndex " << dev->GetIfIndex () << " Ipv6InterfaceIndex " << interface); - NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ()); - if (!route->GetGateway ().IsEqual (Ipv6Address::GetAny ())) { if (outInterface->IsUp ()) { NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ()); + packet->AddHeader (ipHeader); + NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ()); m_txTrace (packet, interface); outInterface->Send (packet, route->GetGateway ()); } else { NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ()); - m_dropTrace (packet); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); } } else @@ -737,13 +737,15 @@ void Ipv6L3Protocol::SendRealOut (Ptr route, Ptr packet, Ipv6 if (outInterface->IsUp ()) { NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestinationAddress ()); + packet->AddHeader (ipHeader); + NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ()); m_txTrace (packet, interface); outInterface->Send (packet, ipHeader.GetDestinationAddress ()); } else { NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestinationAddress ()); - m_dropTrace (packet); + m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, interface); } } } @@ -766,6 +768,8 @@ void Ipv6L3Protocol::IpForward (Ptr rtentry, Ptr p, con if (ipHeader.GetHopLimit () == 0) { + NS_LOG_WARN ("TTL exceeded. Drop."); + m_dropTrace (ipHeader, packet, DROP_TTL_EXPIRED, 0); // Do not reply to ICMPv6 or to multicast IPv6 address if (ipHeader.GetNextHeader () != Icmpv6L4Protocol::PROT_NUMBER && ipHeader.GetDestinationAddress ().IsMulticast () == false) @@ -773,8 +777,6 @@ void Ipv6L3Protocol::IpForward (Ptr rtentry, Ptr p, con packet->AddHeader (ipHeader); GetIcmpv6 ()->SendErrorTimeExceeded (packet, ipHeader.GetSourceAddress (), Icmpv6Header::ICMPV6_HOPLIMIT); } - NS_LOG_WARN ("TTL exceeded. Drop."); - m_dropTrace (packet); return; } @@ -832,7 +834,7 @@ void Ipv6L3Protocol::IpMulticastForward (Ptr mrtentry, Ptr p, const Ipv6Header& ipH { NS_LOG_FUNCTION (this << p << ipHeader << sockErrno); NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno); - m_dropTrace (p); + m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, 0); } Ipv6Header Ipv6L3Protocol::BuildHeader (Ipv6Address src, Ipv6Address dst, uint8_t protocol, uint16_t payloadSize, uint8_t ttl) diff --git a/src/internet-stack/ipv6-l3-protocol.h b/src/internet-stack/ipv6-l3-protocol.h index 0d213c793..17852e648 100644 --- a/src/internet-stack/ipv6-l3-protocol.h +++ b/src/internet-stack/ipv6-l3-protocol.h @@ -59,6 +59,15 @@ class Ipv6L3Protocol : public Ipv6 * \brief The protocol number for IPv6 (0x86DD). */ static const uint16_t PROT_NUMBER; + + enum DropReason + { + DROP_TTL_EXPIRED = 1, + DROP_NO_ROUTE, + DROP_BAD_CHECKSUM, + DROP_INTERFACE_DOWN, + DROP_ROUTE_ERROR, + }; /** * \brief Constructor. @@ -344,7 +353,7 @@ class Ipv6L3Protocol : public Ipv6 /** * \brief Callback to trace drop packets. */ - TracedCallback > m_dropTrace; + TracedCallback, DropReason, uint32_t> m_dropTrace; /** * \brief Copy constructor. diff --git a/src/internet-stack/wscript b/src/internet-stack/wscript index dec9a0af4..1513c0bb3 100644 --- a/src/internet-stack/wscript +++ b/src/internet-stack/wscript @@ -122,6 +122,7 @@ def build(bld): 'icmpv4.h', 'icmpv6-header.h', 'ipv4-l3-protocol.h', + 'ipv6-l3-protocol.h', 'arp-l3-protocol.h', 'udp-l4-protocol.h', 'tcp-l4-protocol.h', From 13f22f74ca0862125c629957f57956db613544d0 Mon Sep 17 00:00:00 2001 From: "Gustavo J. A. M. Carneiro" Date: Tue, 15 Sep 2009 13:01:28 +0100 Subject: [PATCH 8/8] Fix InternetStackHelper::EnableAsciiAll to work with the new Drop signature --- src/helper/internet-stack-helper.cc | 28 ++++++++++++++++++++++++---- src/helper/internet-stack-helper.h | 11 ++++++++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/helper/internet-stack-helper.cc b/src/helper/internet-stack-helper.cc index 4a074ba2d..23ee1a5d8 100644 --- a/src/helper/internet-stack-helper.cc +++ b/src/helper/internet-stack-helper.cc @@ -338,13 +338,13 @@ InternetStackHelper::EnableAscii (std::ostream &os, NodeContainer n) { Ptr node = *i; oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv4L3Protocol/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEventIpv4, writer)); oss.str (""); oss << "/NodeList/" << node->GetId () << "/$ns3::ArpL3Protocol/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEventArp, writer)); oss.str (""); oss << "/NodeList/" << node->GetId () << "/$ns3::Ipv6L3Protocol/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&InternetStackHelper::AsciiDropEventIpv6, writer)); oss.str (""); } } @@ -428,9 +428,29 @@ InternetStackHelper::GetStream (uint32_t nodeId, uint32_t interfaceId) } void -InternetStackHelper::AsciiDropEvent (Ptr writer, std::string path, Ptr packet) +InternetStackHelper::AsciiDropEventArp (Ptr writer, std::string path, Ptr packet) { writer->WritePacket (AsciiWriter::DROP, path, packet); } +void +InternetStackHelper::AsciiDropEventIpv4 (Ptr writer, std::string path, + Ipv4Header const &header, Ptr packet, + Ipv4L3Protocol::DropReason reason, uint32_t interface) +{ + Ptr p = packet->Copy (); + p->AddHeader (header); + writer->WritePacket (AsciiWriter::DROP, path, p); +} + +void +InternetStackHelper::AsciiDropEventIpv6 (Ptr writer, std::string path, + Ipv6Header const &header, Ptr packet, + Ipv6L3Protocol::DropReason reason, uint32_t interface) +{ + Ptr p = packet->Copy (); + p->AddHeader (header); + writer->WritePacket (AsciiWriter::DROP, path, p); +} + } // namespace ns3 diff --git a/src/helper/internet-stack-helper.h b/src/helper/internet-stack-helper.h index 2e9bcb269..ff96d22d2 100644 --- a/src/helper/internet-stack-helper.h +++ b/src/helper/internet-stack-helper.h @@ -28,6 +28,8 @@ #include "ns3/object-factory.h" #include "ns3/pcap-writer.h" #include "ns3/ascii-writer.h" +#include "ns3/ipv4-l3-protocol.h" +#include "ns3/ipv6-l3-protocol.h" namespace ns3 { @@ -198,7 +200,14 @@ private: uint32_t interfaceId; Ptr writer; }; - static void AsciiDropEvent (Ptr writer, std::string path, Ptr packet); + + static void AsciiDropEventIpv4 (Ptr writer, std::string path, + Ipv4Header const &header, Ptr packet, + Ipv4L3Protocol::DropReason reason, uint32_t interface); + static void AsciiDropEventArp (Ptr writer, std::string path, Ptr packet); + static void AsciiDropEventIpv6 (Ptr writer, std::string path, + Ipv6Header const &header, Ptr packet, + Ipv6L3Protocol::DropReason reason, uint32_t interface); static std::string m_pcapBaseFilename; static uint32_t GetNodeIndex (std::string context); static std::vector m_traces;