Adapt the flow-monitor module to the new module tree layout spec.
--- a/examples/flowmon/flowmon-parse-results.py Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-from __future__ import division
-import sys
-import os
-try:
- from xml.etree import cElementTree as ElementTree
-except ImportError:
- from xml.etree import ElementTree
-
-def parse_time_ns(tm):
- if tm.endswith('ns'):
- return long(tm[:-2])
- raise ValueError(tm)
-
-
-
-class FiveTuple(object):
- __slots__ = ['sourceAddress', 'destinationAddress', 'protocol', 'sourcePort', 'destinationPort']
- def __init__(self, el):
- self.sourceAddress = el.get('sourceAddress')
- self.destinationAddress = el.get('destinationAddress')
- self.sourcePort = int(el.get('sourcePort'))
- self.destinationPort = int(el.get('destinationPort'))
- self.protocol = int(el.get('protocol'))
-
-class Histogram(object):
- __slots__ = 'bins', 'nbins', 'number_of_flows'
- def __init__(self, el=None):
- self.bins = []
- if el is not None:
- #self.nbins = int(el.get('nBins'))
- for bin in el.findall('bin'):
- self.bins.append( (float(bin.get("start")), float(bin.get("width")), int(bin.get("count"))) )
-
-class Flow(object):
- __slots__ = ['flowId', 'delayMean', 'packetLossRatio', 'rxBitrate', 'txBitrate',
- 'fiveTuple', 'packetSizeMean', 'probe_stats_unsorted',
- 'hopCount', 'flowInterruptionsHistogram', 'rx_duration']
- def __init__(self, flow_el):
- self.flowId = int(flow_el.get('flowId'))
- rxPackets = long(flow_el.get('rxPackets'))
- txPackets = long(flow_el.get('txPackets'))
- tx_duration = float(long(flow_el.get('timeLastTxPacket')[:-2]) - long(flow_el.get('timeFirstTxPacket')[:-2]))*1e-9
- rx_duration = float(long(flow_el.get('timeLastRxPacket')[:-2]) - long(flow_el.get('timeFirstRxPacket')[:-2]))*1e-9
- self.rx_duration = rx_duration
- self.probe_stats_unsorted = []
- if rxPackets:
- self.hopCount = float(flow_el.get('timesForwarded')) / rxPackets + 1
- else:
- self.hopCount = -1000
- if rxPackets:
- self.delayMean = float(flow_el.get('delaySum')[:-2]) / rxPackets * 1e-9
- self.packetSizeMean = float(flow_el.get('rxBytes')) / rxPackets
- else:
- self.delayMean = None
- self.packetSizeMean = None
- if rx_duration > 0:
- self.rxBitrate = long(flow_el.get('rxBytes'))*8 / rx_duration
- else:
- self.rxBitrate = None
- if tx_duration > 0:
- self.txBitrate = long(flow_el.get('txBytes'))*8 / tx_duration
- else:
- self.txBitrate = None
- lost = float(flow_el.get('lostPackets'))
- #print "rxBytes: %s; txPackets: %s; rxPackets: %s; lostPackets: %s" % (flow_el.get('rxBytes'), txPackets, rxPackets, lost)
- if rxPackets == 0:
- self.packetLossRatio = None
- else:
- self.packetLossRatio = (lost / (rxPackets + lost))
-
- interrupt_hist_elem = flow_el.find("flowInterruptionsHistogram")
- if interrupt_hist_elem is None:
- self.flowInterruptionsHistogram = None
- else:
- self.flowInterruptionsHistogram = Histogram(interrupt_hist_elem)
-
-
-class ProbeFlowStats(object):
- __slots__ = ['probeId', 'packets', 'bytes', 'delayFromFirstProbe']
-
-class Simulation(object):
- def __init__(self, simulation_el):
- self.flows = []
- FlowClassifier_el, = simulation_el.findall("Ipv4FlowClassifier")
- flow_map = {}
- for flow_el in simulation_el.findall("FlowStats/Flow"):
- flow = Flow(flow_el)
- flow_map[flow.flowId] = flow
- self.flows.append(flow)
- for flow_cls in FlowClassifier_el.findall("Flow"):
- flowId = int(flow_cls.get('flowId'))
- flow_map[flowId].fiveTuple = FiveTuple(flow_cls)
-
- for probe_elem in simulation_el.findall("FlowProbes/FlowProbe"):
- probeId = int(probe_elem.get('index'))
- for stats in probe_elem.findall("FlowStats"):
- flowId = int(stats.get('flowId'))
- s = ProbeFlowStats()
- s.packets = int(stats.get('packets'))
- s.bytes = long(stats.get('bytes'))
- s.probeId = probeId
- if s.packets > 0:
- s.delayFromFirstProbe = parse_time_ns(stats.get('delayFromFirstProbeSum')) / float(s.packets)
- else:
- s.delayFromFirstProbe = 0
- flow_map[flowId].probe_stats_unsorted.append(s)
-
-
-def main(argv):
- file_obj = open(argv[1])
- print "Reading XML file ",
-
- sys.stdout.flush()
- level = 0
- sim_list = []
- for event, elem in ElementTree.iterparse(file_obj, events=("start", "end")):
- if event == "start":
- level += 1
- if event == "end":
- level -= 1
- if level == 0 and elem.tag == 'FlowMonitor':
- sim = Simulation(elem)
- sim_list.append(sim)
- elem.clear() # won't need this any more
- sys.stdout.write(".")
- sys.stdout.flush()
- print " done."
-
-
- for sim in sim_list:
- for flow in sim.flows:
- t = flow.fiveTuple
- proto = {6: 'TCP', 17: 'UDP'} [t.protocol]
- print "FlowID: %i (%s %s/%s --> %s/%i)" % \
- (flow.flowId, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort)
- print "\tTX bitrate: %.2f kbit/s" % (flow.txBitrate*1e-3,)
- print "\tRX bitrate: %.2f kbit/s" % (flow.rxBitrate*1e-3,)
- print "\tMean Delay: %.2f ms" % (flow.delayMean*1e3,)
- print "\tPacket Loss Ratio: %.2f %%" % (flow.packetLossRatio*100)
-
-
-if __name__ == '__main__':
- main(sys.argv)
--- a/examples/flowmon/waf Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-exec "`dirname "$0"`"/../../waf "$@"
--- a/examples/flowmon/wifi-olsr-flowmon.py Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-# -*- Mode: Python; -*-
-# 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
-#
-# Authors: Gustavo Carneiro <gjc@inescporto.pt>
-
-import sys
-import ns3
-
-DISTANCE = 100 # (m)
-NUM_NODES_SIDE = 3
-
-def main(argv):
-
- cmd = ns3.CommandLine()
-
- cmd.NumNodesSide = None
- cmd.AddValue("NumNodesSide", "Grid side number of nodes (total number of nodes will be this number squared)")
-
- cmd.Results = None
- cmd.AddValue("Results", "Write XML results to file")
-
- cmd.Plot = None
- cmd.AddValue("Plot", "Plot the results using the matplotlib python module")
-
- cmd.Parse(argv)
-
- wifi = ns3.WifiHelper.Default()
- wifiMac = ns3.NqosWifiMacHelper.Default()
- wifiPhy = ns3.YansWifiPhyHelper.Default()
- wifiChannel = ns3.YansWifiChannelHelper.Default()
- wifiPhy.SetChannel(wifiChannel.Create())
- ssid = ns3.Ssid("wifi-default")
- wifi.SetRemoteStationManager("ns3::ArfWifiManager")
- wifiMac.SetType ("ns3::AdhocWifiMac", "Ssid", ns3.SsidValue(ssid))
-
- internet = ns3.InternetStackHelper()
- list_routing = ns3.Ipv4ListRoutingHelper()
- olsr_routing = ns3.OlsrHelper()
- static_routing = ns3.Ipv4StaticRoutingHelper()
- list_routing.Add(static_routing, 0)
- list_routing.Add(olsr_routing, 100)
- internet.SetRoutingHelper(list_routing)
-
- ipv4Addresses = ns3.Ipv4AddressHelper()
- ipv4Addresses.SetBase(ns3.Ipv4Address("10.0.0.0"), ns3.Ipv4Mask("255.255.255.0"))
-
- port = 9 # Discard port(RFC 863)
- onOffHelper = ns3.OnOffHelper("ns3::UdpSocketFactory",
- ns3.Address(ns3.InetSocketAddress(ns3.Ipv4Address("10.0.0.1"), port)))
- onOffHelper.SetAttribute("DataRate", ns3.DataRateValue(ns3.DataRate("100kbps")))
- onOffHelper.SetAttribute("OnTime", ns3.RandomVariableValue(ns3.ConstantVariable(1)))
- onOffHelper.SetAttribute("OffTime", ns3.RandomVariableValue(ns3.ConstantVariable(0)))
-
- addresses = []
- nodes = []
-
- if cmd.NumNodesSide is None:
- num_nodes_side = NUM_NODES_SIDE
- else:
- num_nodes_side = int(cmd.NumNodesSide)
-
- for xi in range(num_nodes_side):
- for yi in range(num_nodes_side):
-
- node = ns3.Node()
- nodes.append(node)
-
- internet.Install(ns3.NodeContainer(node))
-
- mobility = ns3.ConstantPositionMobilityModel()
- mobility.SetPosition(ns3.Vector(xi*DISTANCE, yi*DISTANCE, 0))
- node.AggregateObject(mobility)
-
- devices = wifi.Install(wifiPhy, wifiMac, node)
- ipv4_interfaces = ipv4Addresses.Assign(devices)
- addresses.append(ipv4_interfaces.GetAddress(0))
-
- for i, node in enumerate(nodes):
- destaddr = addresses[(len(addresses) - 1 - i) % len(addresses)]
- #print i, destaddr
- onOffHelper.SetAttribute("Remote", ns3.AddressValue(ns3.InetSocketAddress(destaddr, port)))
- app = onOffHelper.Install(ns3.NodeContainer(node))
- app.Start(ns3.Seconds(ns3.UniformVariable(20, 30).GetValue()))
-
- #internet.EnablePcapAll("wifi-olsr")
- flowmon_helper = ns3.FlowMonitorHelper()
- #flowmon_helper.SetMonitorAttribute("StartTime", ns3.TimeValue(ns3.Seconds(31)))
- monitor = flowmon_helper.InstallAll()
- monitor.SetAttribute("DelayBinWidth", ns3.DoubleValue(0.001))
- monitor.SetAttribute("JitterBinWidth", ns3.DoubleValue(0.001))
- monitor.SetAttribute("PacketSizeBinWidth", ns3.DoubleValue(20))
-
- ns3.Simulator.Stop(ns3.Seconds(44.0))
- ns3.Simulator.Run()
-
- def print_stats(os, st):
- print >> os, " Tx Bytes: ", st.txBytes
- print >> os, " Rx Bytes: ", st.rxBytes
- print >> os, " Tx Packets: ", st.txPackets
- print >> os, " Rx Packets: ", st.rxPackets
- print >> os, " Lost Packets: ", st.lostPackets
- if st.rxPackets > 0:
- print >> os, " Mean{Delay}: ", (st.delaySum.GetSeconds() / st.rxPackets)
- print >> os, " Mean{Jitter}: ", (st.jitterSum.GetSeconds() / (st.rxPackets-1))
- print >> os, " Mean{Hop Count}: ", float(st.timesForwarded) / st.rxPackets + 1
-
- if 0:
- print >> os, "Delay Histogram"
- for i in range(st.delayHistogram.GetNBins () ):
- print >> os, " ",i,"(", st.delayHistogram.GetBinStart (i), "-", \
- st.delayHistogram.GetBinEnd (i), "): ", st.delayHistogram.GetBinCount (i)
- print >> os, "Jitter Histogram"
- for i in range(st.jitterHistogram.GetNBins () ):
- print >> os, " ",i,"(", st.jitterHistogram.GetBinStart (i), "-", \
- st.jitterHistogram.GetBinEnd (i), "): ", st.jitterHistogram.GetBinCount (i)
- print >> os, "PacketSize Histogram"
- for i in range(st.packetSizeHistogram.GetNBins () ):
- print >> os, " ",i,"(", st.packetSizeHistogram.GetBinStart (i), "-", \
- st.packetSizeHistogram.GetBinEnd (i), "): ", st.packetSizeHistogram.GetBinCount (i)
-
- for reason, drops in enumerate(st.packetsDropped):
- print " Packets dropped by reason %i: %i" % (reason, drops)
- #for reason, drops in enumerate(st.bytesDropped):
- # print "Bytes dropped by reason %i: %i" % (reason, drops)
-
- monitor.CheckForLostPackets()
- classifier = flowmon_helper.GetClassifier()
-
- if cmd.Results is None:
- for flow_id, flow_stats in monitor.GetFlowStats():
- t = classifier.FindFlow(flow_id)
- proto = {6: 'TCP', 17: 'UDP'} [t.protocol]
- print "FlowID: %i (%s %s/%s --> %s/%i)" % \
- (flow_id, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort)
- print_stats(sys.stdout, flow_stats)
- else:
- print monitor.SerializeToXmlFile(cmd.Results, True, True)
-
-
- if cmd.Plot is not None:
- import pylab
- delays = []
- for flow_id, flow_stats in monitor.GetFlowStats():
- tupl = classifier.FindFlow(flow_id)
- if tupl.protocol == 17 and tupl.sourcePort == 698:
- continue
- delays.append(flow_stats.delaySum.GetSeconds() / flow_stats.rxPackets)
- pylab.hist(delays, 20)
- pylab.xlabel("Delay (s)")
- pylab.ylabel("Number of Flows")
- pylab.show()
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
-
--- a/examples/flowmon/wscript Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,4 +0,0 @@
-## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
-
-def build(bld):
- pass
--- a/src/contrib/flow-monitor/design.txt Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-
-* 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
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/doc/design.txt Fri Oct 22 17:18:49 2010 +0100
@@ -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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/examples/flowmon-parse-results.py Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,143 @@
+from __future__ import division
+import sys
+import os
+try:
+ from xml.etree import cElementTree as ElementTree
+except ImportError:
+ from xml.etree import ElementTree
+
+def parse_time_ns(tm):
+ if tm.endswith('ns'):
+ return long(tm[:-2])
+ raise ValueError(tm)
+
+
+
+class FiveTuple(object):
+ __slots__ = ['sourceAddress', 'destinationAddress', 'protocol', 'sourcePort', 'destinationPort']
+ def __init__(self, el):
+ self.sourceAddress = el.get('sourceAddress')
+ self.destinationAddress = el.get('destinationAddress')
+ self.sourcePort = int(el.get('sourcePort'))
+ self.destinationPort = int(el.get('destinationPort'))
+ self.protocol = int(el.get('protocol'))
+
+class Histogram(object):
+ __slots__ = 'bins', 'nbins', 'number_of_flows'
+ def __init__(self, el=None):
+ self.bins = []
+ if el is not None:
+ #self.nbins = int(el.get('nBins'))
+ for bin in el.findall('bin'):
+ self.bins.append( (float(bin.get("start")), float(bin.get("width")), int(bin.get("count"))) )
+
+class Flow(object):
+ __slots__ = ['flowId', 'delayMean', 'packetLossRatio', 'rxBitrate', 'txBitrate',
+ 'fiveTuple', 'packetSizeMean', 'probe_stats_unsorted',
+ 'hopCount', 'flowInterruptionsHistogram', 'rx_duration']
+ def __init__(self, flow_el):
+ self.flowId = int(flow_el.get('flowId'))
+ rxPackets = long(flow_el.get('rxPackets'))
+ txPackets = long(flow_el.get('txPackets'))
+ tx_duration = float(long(flow_el.get('timeLastTxPacket')[:-2]) - long(flow_el.get('timeFirstTxPacket')[:-2]))*1e-9
+ rx_duration = float(long(flow_el.get('timeLastRxPacket')[:-2]) - long(flow_el.get('timeFirstRxPacket')[:-2]))*1e-9
+ self.rx_duration = rx_duration
+ self.probe_stats_unsorted = []
+ if rxPackets:
+ self.hopCount = float(flow_el.get('timesForwarded')) / rxPackets + 1
+ else:
+ self.hopCount = -1000
+ if rxPackets:
+ self.delayMean = float(flow_el.get('delaySum')[:-2]) / rxPackets * 1e-9
+ self.packetSizeMean = float(flow_el.get('rxBytes')) / rxPackets
+ else:
+ self.delayMean = None
+ self.packetSizeMean = None
+ if rx_duration > 0:
+ self.rxBitrate = long(flow_el.get('rxBytes'))*8 / rx_duration
+ else:
+ self.rxBitrate = None
+ if tx_duration > 0:
+ self.txBitrate = long(flow_el.get('txBytes'))*8 / tx_duration
+ else:
+ self.txBitrate = None
+ lost = float(flow_el.get('lostPackets'))
+ #print "rxBytes: %s; txPackets: %s; rxPackets: %s; lostPackets: %s" % (flow_el.get('rxBytes'), txPackets, rxPackets, lost)
+ if rxPackets == 0:
+ self.packetLossRatio = None
+ else:
+ self.packetLossRatio = (lost / (rxPackets + lost))
+
+ interrupt_hist_elem = flow_el.find("flowInterruptionsHistogram")
+ if interrupt_hist_elem is None:
+ self.flowInterruptionsHistogram = None
+ else:
+ self.flowInterruptionsHistogram = Histogram(interrupt_hist_elem)
+
+
+class ProbeFlowStats(object):
+ __slots__ = ['probeId', 'packets', 'bytes', 'delayFromFirstProbe']
+
+class Simulation(object):
+ def __init__(self, simulation_el):
+ self.flows = []
+ FlowClassifier_el, = simulation_el.findall("Ipv4FlowClassifier")
+ flow_map = {}
+ for flow_el in simulation_el.findall("FlowStats/Flow"):
+ flow = Flow(flow_el)
+ flow_map[flow.flowId] = flow
+ self.flows.append(flow)
+ for flow_cls in FlowClassifier_el.findall("Flow"):
+ flowId = int(flow_cls.get('flowId'))
+ flow_map[flowId].fiveTuple = FiveTuple(flow_cls)
+
+ for probe_elem in simulation_el.findall("FlowProbes/FlowProbe"):
+ probeId = int(probe_elem.get('index'))
+ for stats in probe_elem.findall("FlowStats"):
+ flowId = int(stats.get('flowId'))
+ s = ProbeFlowStats()
+ s.packets = int(stats.get('packets'))
+ s.bytes = long(stats.get('bytes'))
+ s.probeId = probeId
+ if s.packets > 0:
+ s.delayFromFirstProbe = parse_time_ns(stats.get('delayFromFirstProbeSum')) / float(s.packets)
+ else:
+ s.delayFromFirstProbe = 0
+ flow_map[flowId].probe_stats_unsorted.append(s)
+
+
+def main(argv):
+ file_obj = open(argv[1])
+ print "Reading XML file ",
+
+ sys.stdout.flush()
+ level = 0
+ sim_list = []
+ for event, elem in ElementTree.iterparse(file_obj, events=("start", "end")):
+ if event == "start":
+ level += 1
+ if event == "end":
+ level -= 1
+ if level == 0 and elem.tag == 'FlowMonitor':
+ sim = Simulation(elem)
+ sim_list.append(sim)
+ elem.clear() # won't need this any more
+ sys.stdout.write(".")
+ sys.stdout.flush()
+ print " done."
+
+
+ for sim in sim_list:
+ for flow in sim.flows:
+ t = flow.fiveTuple
+ proto = {6: 'TCP', 17: 'UDP'} [t.protocol]
+ print "FlowID: %i (%s %s/%s --> %s/%i)" % \
+ (flow.flowId, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort)
+ print "\tTX bitrate: %.2f kbit/s" % (flow.txBitrate*1e-3,)
+ print "\tRX bitrate: %.2f kbit/s" % (flow.rxBitrate*1e-3,)
+ print "\tMean Delay: %.2f ms" % (flow.delayMean*1e3,)
+ print "\tPacket Loss Ratio: %.2f %%" % (flow.packetLossRatio*100)
+
+
+if __name__ == '__main__':
+ main(sys.argv)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/examples/wifi-olsr-flowmon.py Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,171 @@
+# -*- Mode: Python; -*-
+# 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
+#
+# Authors: Gustavo Carneiro <gjc@inescporto.pt>
+
+import sys
+import ns3
+
+DISTANCE = 100 # (m)
+NUM_NODES_SIDE = 3
+
+def main(argv):
+
+ cmd = ns3.CommandLine()
+
+ cmd.NumNodesSide = None
+ cmd.AddValue("NumNodesSide", "Grid side number of nodes (total number of nodes will be this number squared)")
+
+ cmd.Results = None
+ cmd.AddValue("Results", "Write XML results to file")
+
+ cmd.Plot = None
+ cmd.AddValue("Plot", "Plot the results using the matplotlib python module")
+
+ cmd.Parse(argv)
+
+ wifi = ns3.WifiHelper.Default()
+ wifiMac = ns3.NqosWifiMacHelper.Default()
+ wifiPhy = ns3.YansWifiPhyHelper.Default()
+ wifiChannel = ns3.YansWifiChannelHelper.Default()
+ wifiPhy.SetChannel(wifiChannel.Create())
+ ssid = ns3.Ssid("wifi-default")
+ wifi.SetRemoteStationManager("ns3::ArfWifiManager")
+ wifiMac.SetType ("ns3::AdhocWifiMac", "Ssid", ns3.SsidValue(ssid))
+
+ internet = ns3.InternetStackHelper()
+ list_routing = ns3.Ipv4ListRoutingHelper()
+ olsr_routing = ns3.OlsrHelper()
+ static_routing = ns3.Ipv4StaticRoutingHelper()
+ list_routing.Add(static_routing, 0)
+ list_routing.Add(olsr_routing, 100)
+ internet.SetRoutingHelper(list_routing)
+
+ ipv4Addresses = ns3.Ipv4AddressHelper()
+ ipv4Addresses.SetBase(ns3.Ipv4Address("10.0.0.0"), ns3.Ipv4Mask("255.255.255.0"))
+
+ port = 9 # Discard port(RFC 863)
+ onOffHelper = ns3.OnOffHelper("ns3::UdpSocketFactory",
+ ns3.Address(ns3.InetSocketAddress(ns3.Ipv4Address("10.0.0.1"), port)))
+ onOffHelper.SetAttribute("DataRate", ns3.DataRateValue(ns3.DataRate("100kbps")))
+ onOffHelper.SetAttribute("OnTime", ns3.RandomVariableValue(ns3.ConstantVariable(1)))
+ onOffHelper.SetAttribute("OffTime", ns3.RandomVariableValue(ns3.ConstantVariable(0)))
+
+ addresses = []
+ nodes = []
+
+ if cmd.NumNodesSide is None:
+ num_nodes_side = NUM_NODES_SIDE
+ else:
+ num_nodes_side = int(cmd.NumNodesSide)
+
+ for xi in range(num_nodes_side):
+ for yi in range(num_nodes_side):
+
+ node = ns3.Node()
+ nodes.append(node)
+
+ internet.Install(ns3.NodeContainer(node))
+
+ mobility = ns3.ConstantPositionMobilityModel()
+ mobility.SetPosition(ns3.Vector(xi*DISTANCE, yi*DISTANCE, 0))
+ node.AggregateObject(mobility)
+
+ devices = wifi.Install(wifiPhy, wifiMac, node)
+ ipv4_interfaces = ipv4Addresses.Assign(devices)
+ addresses.append(ipv4_interfaces.GetAddress(0))
+
+ for i, node in enumerate(nodes):
+ destaddr = addresses[(len(addresses) - 1 - i) % len(addresses)]
+ #print i, destaddr
+ onOffHelper.SetAttribute("Remote", ns3.AddressValue(ns3.InetSocketAddress(destaddr, port)))
+ app = onOffHelper.Install(ns3.NodeContainer(node))
+ app.Start(ns3.Seconds(ns3.UniformVariable(20, 30).GetValue()))
+
+ #internet.EnablePcapAll("wifi-olsr")
+ flowmon_helper = ns3.FlowMonitorHelper()
+ #flowmon_helper.SetMonitorAttribute("StartTime", ns3.TimeValue(ns3.Seconds(31)))
+ monitor = flowmon_helper.InstallAll()
+ monitor.SetAttribute("DelayBinWidth", ns3.DoubleValue(0.001))
+ monitor.SetAttribute("JitterBinWidth", ns3.DoubleValue(0.001))
+ monitor.SetAttribute("PacketSizeBinWidth", ns3.DoubleValue(20))
+
+ ns3.Simulator.Stop(ns3.Seconds(44.0))
+ ns3.Simulator.Run()
+
+ def print_stats(os, st):
+ print >> os, " Tx Bytes: ", st.txBytes
+ print >> os, " Rx Bytes: ", st.rxBytes
+ print >> os, " Tx Packets: ", st.txPackets
+ print >> os, " Rx Packets: ", st.rxPackets
+ print >> os, " Lost Packets: ", st.lostPackets
+ if st.rxPackets > 0:
+ print >> os, " Mean{Delay}: ", (st.delaySum.GetSeconds() / st.rxPackets)
+ print >> os, " Mean{Jitter}: ", (st.jitterSum.GetSeconds() / (st.rxPackets-1))
+ print >> os, " Mean{Hop Count}: ", float(st.timesForwarded) / st.rxPackets + 1
+
+ if 0:
+ print >> os, "Delay Histogram"
+ for i in range(st.delayHistogram.GetNBins () ):
+ print >> os, " ",i,"(", st.delayHistogram.GetBinStart (i), "-", \
+ st.delayHistogram.GetBinEnd (i), "): ", st.delayHistogram.GetBinCount (i)
+ print >> os, "Jitter Histogram"
+ for i in range(st.jitterHistogram.GetNBins () ):
+ print >> os, " ",i,"(", st.jitterHistogram.GetBinStart (i), "-", \
+ st.jitterHistogram.GetBinEnd (i), "): ", st.jitterHistogram.GetBinCount (i)
+ print >> os, "PacketSize Histogram"
+ for i in range(st.packetSizeHistogram.GetNBins () ):
+ print >> os, " ",i,"(", st.packetSizeHistogram.GetBinStart (i), "-", \
+ st.packetSizeHistogram.GetBinEnd (i), "): ", st.packetSizeHistogram.GetBinCount (i)
+
+ for reason, drops in enumerate(st.packetsDropped):
+ print " Packets dropped by reason %i: %i" % (reason, drops)
+ #for reason, drops in enumerate(st.bytesDropped):
+ # print "Bytes dropped by reason %i: %i" % (reason, drops)
+
+ monitor.CheckForLostPackets()
+ classifier = flowmon_helper.GetClassifier()
+
+ if cmd.Results is None:
+ for flow_id, flow_stats in monitor.GetFlowStats():
+ t = classifier.FindFlow(flow_id)
+ proto = {6: 'TCP', 17: 'UDP'} [t.protocol]
+ print "FlowID: %i (%s %s/%s --> %s/%i)" % \
+ (flow_id, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort)
+ print_stats(sys.stdout, flow_stats)
+ else:
+ print monitor.SerializeToXmlFile(cmd.Results, True, True)
+
+
+ if cmd.Plot is not None:
+ import pylab
+ delays = []
+ for flow_id, flow_stats in monitor.GetFlowStats():
+ tupl = classifier.FindFlow(flow_id)
+ if tupl.protocol == 17 and tupl.sourcePort == 698:
+ continue
+ delays.append(flow_stats.delaySum.GetSeconds() / flow_stats.rxPackets)
+ pylab.hist(delays, 20)
+ pylab.xlabel("Delay (s)")
+ pylab.ylabel("Number of Flows")
+ pylab.show()
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
+
--- a/src/contrib/flow-monitor/flow-classifier.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#include "flow-classifier.h"
-
-namespace ns3 {
-
-FlowClassifier::FlowClassifier ()
- :
- m_lastNewFlowId (0)
-{
-}
-
-FlowClassifier::~FlowClassifier ()
-{}
-
-FlowId
-FlowClassifier::GetNewFlowId ()
-{
- return ++m_lastNewFlowId;
-}
-
-
-} // namespace ns3
-
--- a/src/contrib/flow-monitor/flow-classifier.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#ifndef __FLOW_CLASSIFIER_H__
-#define __FLOW_CLASSIFIER_H__
-
-#include "ns3/simple-ref-count.h"
-#include <ostream>
-
-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 SimpleRefCount<FlowClassifier>
-{
-private:
- FlowId m_lastNewFlowId;
-
- FlowClassifier (FlowClassifier const &);
- FlowClassifier& operator= (FlowClassifier const &);
-
-public:
-
- FlowClassifier ();
- virtual ~FlowClassifier ();
-
- virtual void SerializeToXmlStream (std::ostream &os, int indent) const = 0;
-
-protected:
- FlowId GetNewFlowId ();
-
-};
-
-
-} // namespace ns3
-
-#endif
-
--- a/src/contrib/flow-monitor/flow-monitor.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,487 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#include "flow-monitor.h"
-#include "ns3/simulator.h"
-#include "ns3/log.h"
-#include "ns3/double.h"
-#include <fstream>
-#include <sstream>
-
-#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<Object> ()
- .AddConstructor<FlowMonitor> ()
- .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 <double> ())
- .AddAttribute ("JitterBinWidth", ("The width used in the jitter histogram."),
- DoubleValue (0.001),
- MakeDoubleAccessor (&FlowMonitor::m_jitterBinWidth),
- MakeDoubleChecker <double> ())
- .AddAttribute ("PacketSizeBinWidth", ("The width used in the packetSize histogram."),
- DoubleValue (20),
- MakeDoubleAccessor (&FlowMonitor::m_packetSizeBinWidth),
- MakeDoubleChecker <double> ())
- .AddAttribute ("FlowInterruptionsBinWidth", ("The width used in the flowInterruptions histogram."),
- DoubleValue (0.250),
- MakeDoubleAccessor (&FlowMonitor::m_flowInterruptionsBinWidth),
- MakeDoubleChecker <double> ())
- .AddAttribute ("FlowInterruptionsMinTime", ("The minimum inter-arrival time that is considered a flow interruption."),
- TimeValue (Seconds (0.5)),
- MakeTimeAccessor (&FlowMonitor::m_flowInterruptionsMinTime),
- MakeTimeChecker ())
- ;
- 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<FlowId, FlowStats>::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);
- ref.flowInterruptionsHistogram.SetDefaultBinWidth (m_flowInterruptionsBinWidth);
- return ref;
- }
- else
- {
- return iter->second;
- }
-}
-
-
-void
-FlowMonitor::ReportFirstTx (Ptr<FlowProbe> 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<FlowProbe> probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize)
-{
- if (!m_enabled)
- {
- return;
- }
- std::pair<FlowId, FlowPacketId> 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<FlowProbe> 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;
- }
- else
- {
- // measure possible flow interruptions
- Time interArrivalTime = now - stats.timeLastRxPacket;
- if (interArrivalTime > m_flowInterruptionsMinTime)
- {
- stats.flowInterruptionsHistogram.AddValue (interArrivalTime.GetSeconds ());
- }
- }
- 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<FlowProbe> 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<FlowId, FlowMonitor::FlowStats>
-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<FlowId, FlowStats>::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<FlowProbe> probe)
-{
- m_flowProbes.push_back (probe);
-}
-
-std::vector< Ptr<FlowProbe> >
-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<FlowMonitor> (this));
-}
-
-void
-FlowMonitor::Stop (const Time &time)
-{
- if (!m_enabled)
- {
- return;
- }
- Simulator::Cancel (m_stopEvent);
- m_stopEvent = Simulator::Schedule (time, &FlowMonitor::StopRightNow, Ptr<FlowMonitor> (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<FlowClassifier> classifier)
-{
- m_classifier = classifier;
-}
-
-void
-FlowMonitor::SerializeToXmlStream (std::ostream &os, int indent, bool enableHistograms, bool enableProbes)
-{
- CheckForLostPackets ();
-
- INDENT(indent); os << "<FlowMonitor>\n";
- indent += 2;
- INDENT(indent); os << "<FlowStats>\n";
- indent += 2;
- for (std::map<FlowId, FlowStats>::const_iterator flowI = m_flowStats.begin ();
- flowI != m_flowStats.end (); flowI++)
- {
-
- INDENT(indent);
-#define ATTRIB(name) << " "#name"=\"" << flowI->second.name << "\""
- os << "<Flow flowId=\"" << flowI->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 << "<packetsDropped reasonCode=\"" << reasonCode << "\""
- << " number=\"" << flowI->second.packetsDropped[reasonCode]
- << "\" />\n";
- }
- for (uint32_t reasonCode = 0; reasonCode < flowI->second.bytesDropped.size (); reasonCode++)
- {
- INDENT(indent);
- os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
- << " bytes=\"" << flowI->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");
- flowI->second.flowInterruptionsHistogram.SerializeToXmlStream (os, indent, "flowInterruptionsHistogram");
- }
- indent -= 2;
-
- INDENT(indent); os << "</Flow>\n";
- }
- indent -= 2;
- INDENT(indent); os << "</FlowStats>\n";
-
- m_classifier->SerializeToXmlStream (os, indent);
-
- if (enableProbes)
- {
- INDENT(indent); os << "<FlowProbes>\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 << "</FlowProbes>\n";
- }
-
- indent -= 2;
- INDENT(indent); os << "</FlowMonitor>\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 << "<?xml version=\"1.0\" ?>\n";
- SerializeToXmlStream (os, 0, enableHistograms, enableProbes);
- os.close ();
-}
-
-
-} // namespace ns3
-
--- a/src/contrib/flow-monitor/flow-monitor.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,247 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#ifndef __FLOW_MONITOR_H__
-#define __FLOW_MONITOR_H__
-
-#include <vector>
-#include <map>
-
-#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 {
-
-/// \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;
-
- /// 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<uint32_t> packetsDropped; // packetsDropped[reasonCode] => number of dropped packets
-
- /// This attribute also tracks the number of lost bytes. See also
- /// comment in attribute packetsDropped.
- std::vector<uint64_t> bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes
- Histogram flowInterruptionsHistogram; // histogram of durations of flow interruptions
- };
-
- // --- basic methods ---
- static TypeId GetTypeId ();
- TypeId GetInstanceTypeId () const;
- FlowMonitor ();
-
- /// Set the FlowClassifier to be used by the flow monitor.
- void SetFlowClassifier (Ptr<FlowClassifier> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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 ---
- /// 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<FlowId, FlowStats> GetFlowStats () const;
-
- /// Get a list of all FlowProbe's associated with this FlowMonitor
- std::vector< Ptr<FlowProbe> > 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);
-
-
-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<FlowId, FlowStats> m_flowStats;
-
- // (FlowId,PacketId) --> TrackedPacket
- typedef std::map< std::pair<FlowId, FlowPacketId>, TrackedPacket> TrackedPacketMap;
- TrackedPacketMap m_trackedPackets;
- Time m_maxPerHopDelay;
- std::vector< Ptr<FlowProbe> > m_flowProbes;
-
- // note: this is needed only for serialization
- Ptr<FlowClassifier> m_classifier;
-
- EventId m_startEvent;
- EventId m_stopEvent;
- bool m_enabled;
- double m_delayBinWidth;
- double m_jitterBinWidth;
- double m_packetSizeBinWidth;
- double m_flowInterruptionsBinWidth;
- Time m_flowInterruptionsMinTime;
-
- FlowStats& GetStatsForFlow (FlowId flowId);
- void PeriodicCheckForLostPackets ();
-};
-
-
-} // namespace ns3
-
-#endif
-
--- a/src/contrib/flow-monitor/flow-probe.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#include "ns3/flow-probe.h"
-#include "ns3/flow-monitor.h"
-
-namespace ns3 {
-
-
-FlowProbe::~FlowProbe ()
-{
-}
-
-
-FlowProbe::FlowProbe (Ptr<FlowMonitor> 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 << "<FlowProbe index=\"" << index << "\">\n";
-
- indent += 2;
-
- for (Stats::const_iterator iter = m_stats.begin (); iter != m_stats.end (); iter++)
- {
- INDENT(indent);
- os << "<FlowStats "
- << " flowId=\"" << iter->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 << "<packetsDropped reasonCode=\"" << reasonCode << "\""
- << " number=\"" << iter->second.packetsDropped[reasonCode]
- << "\" />\n";
- }
- for (uint32_t reasonCode = 0; reasonCode < iter->second.bytesDropped.size (); reasonCode++)
- {
- INDENT(indent);
- os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
- << " bytes=\"" << iter->second.bytesDropped[reasonCode]
- << "\" />\n";
- }
- indent -= 2;
- INDENT(indent); os << "</FlowStats>\n";
- }
- indent -= 2;
- INDENT(indent); os << "</FlowProbe>\n";
-}
-
-
-
-} // namespace ns3
-
-
--- a/src/contrib/flow-monitor/flow-probe.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#ifndef __FLOW_PROBE_H__
-#define __FLOW_PROBE_H__
-
-#include <map>
-#include <vector>
-
-#include "ns3/simple-ref-count.h"
-#include "ns3/flow-classifier.h"
-#include "ns3/nstime.h"
-
-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 SimpleRefCount<FlowProbe>
-{
-private:
- FlowProbe (FlowProbe const &);
- FlowProbe& operator= (FlowProbe const &);
-
-protected:
-
- FlowProbe (Ptr<FlowMonitor> flowMonitor);
-
-public:
- virtual ~FlowProbe ();
-
- struct FlowStats
- {
- FlowStats () : delayFromFirstProbeSum (Seconds (0)), bytes (0), packets (0) {}
-
- /// packetsDropped[reasonCode] => number of dropped packets
- std::vector<uint32_t> packetsDropped;
- /// bytesDropped[reasonCode] => number of dropped bytes
- std::vector<uint64_t> 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;
- };
-
- typedef std::map<FlowId, FlowStats> Stats;
-
- 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;
-
-protected:
- Ptr<FlowMonitor> m_flowMonitor;
- Stats m_stats;
-
-};
-
-
-} // namespace ns3
-
-#endif
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/helper/flow-monitor-helper.cc Fri Oct 22 17:18:49 2010 +0100
@@ -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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#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<FlowMonitor>
+FlowMonitorHelper::GetMonitor ()
+{
+ if (!m_flowMonitor)
+ {
+ m_flowMonitor = m_monitorFactory.Create<FlowMonitor> ();
+ m_flowClassifier = Create<Ipv4FlowClassifier> ();
+ m_flowMonitor->SetFlowClassifier (m_flowClassifier);
+ }
+ return m_flowMonitor;
+}
+
+
+Ptr<FlowClassifier>
+FlowMonitorHelper::GetClassifier ()
+{
+ if (!m_flowClassifier)
+ {
+ m_flowClassifier = Create<Ipv4FlowClassifier> ();
+ }
+ return m_flowClassifier;
+}
+
+
+Ptr<FlowMonitor>
+FlowMonitorHelper::Install (Ptr<Node> node)
+{
+ Ptr<FlowMonitor> monitor = GetMonitor ();
+ Ptr<FlowClassifier> classifier = GetClassifier ();
+ Ptr<Ipv4FlowProbe> probe = Create<Ipv4FlowProbe> (monitor,
+ DynamicCast<Ipv4FlowClassifier> (classifier),
+ node);
+ return m_flowMonitor;
+}
+
+
+Ptr<FlowMonitor>
+FlowMonitorHelper::Install (NodeContainer nodes)
+{
+ for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ if (node->GetObject<Ipv4L3Protocol> ())
+ {
+ Install (node);
+ }
+ }
+ return m_flowMonitor;
+}
+
+Ptr<FlowMonitor>
+FlowMonitorHelper::InstallAll ()
+{
+ for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
+ {
+ Ptr<Node> node = *i;
+ if (node->GetObject<Ipv4L3Protocol> ())
+ {
+ Install (node);
+ }
+ }
+ return m_flowMonitor;
+}
+
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/helper/flow-monitor-helper.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,69 @@
+// -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+#ifndef FLOW_MONITOR_HELPER_H
+#define FLOW_MONITOR_HELPER_H
+
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/flow-monitor.h"
+#include "ns3/flow-classifier.h"
+#include <string>
+
+namespace ns3 {
+
+class AttributeValue;
+class Ipv4FlowClassifier;
+
+/// \brief Helper to enable IPv4 flow monitoring on a set of Nodes
+class FlowMonitorHelper
+{
+public:
+ /// \brief Construct a FlowMonitorHelper class which makes it easier to
+ /// configure and use the FlowMonitor
+ 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
+ /// \param nodes A NodeContainer holding the set of nodes to work with.
+ Ptr<FlowMonitor> Install (NodeContainer nodes);
+ /// \brief Enable flow monitoring on a single node
+ /// \param node A Ptr<Node> to the node on which to enable flow monitoring.
+ Ptr<FlowMonitor> Install (Ptr<Node> node);
+ /// \brief Enable flow monitoring on all nodes
+ Ptr<FlowMonitor> InstallAll ();
+
+ /// \brief Retrieve the FlowMonitor object created by the Install* methods
+ Ptr<FlowMonitor> GetMonitor ();
+
+ /// \brief Retrieve the FlowClassifier object created by the Install* methods
+ Ptr<FlowClassifier> GetClassifier ();
+
+private:
+ ObjectFactory m_monitorFactory;
+ Ptr<FlowMonitor> m_flowMonitor;
+ Ptr<FlowClassifier> m_flowClassifier;
+};
+
+} // namespace ns3
+
+
+#endif /* FLOW_MONITOR_HELPER_H */
--- a/src/contrib/flow-monitor/histogram.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,214 +0,0 @@
-/* -*- 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 <pedro.fortuna@inescporto.pt> <pedro.fortuna@gmail.com>
-//
-
-#include <math.h>
-#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 = (uint32_t)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 << "<bin"
- << " index=\"" << (index) << "\""
- << " start=\"" << (index*m_binWidth) << "\""
- << " width=\"" << m_binWidth << "\""
- << " count=\"" << m_histogram[index] << "\""
- << " />\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 << "</" << elementName << ">\n";
-#undef INDENT
-}
-
-
-
-
-} // namespace ns3
-
-
-#include "ns3/test.h"
-
-namespace ns3 {
-
-class HistogramTestCase : public ns3::TestCase {
-private:
-public:
- HistogramTestCase ();
- virtual bool DoRun (void);
-
-
-};
-
-HistogramTestCase::HistogramTestCase ()
- : ns3::TestCase ("Histogram")
-{}
-
-
-bool
-HistogramTestCase::DoRun (void)
-{
- 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_EXPECT_MSG_EQ_TOL (h0.GetBinWidth (0), 3.5, 1e-6, "");
- NS_TEST_EXPECT_MSG_EQ (h0.GetNBins (), 2, "");
- NS_TEST_EXPECT_MSG_EQ_TOL (h0.GetBinStart (1), 3.5, 1e-6, "");
- NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (0), 10, "");
- NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (1), 5, "");
- }
-
- {
- // Testing bin expansion
- h0.AddValue (74.3);
- NS_TEST_EXPECT_MSG_EQ (h0.GetNBins (), 22, "");
- NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (21), 1, "");
- }
-
- return false;
-}
-
-static class HistogramTestSuite : public TestSuite
-{
-public:
- HistogramTestSuite ()
- : TestSuite ("histogram", UNIT)
- {
- AddTestCase (new HistogramTestCase ());
- }
-} g_HistogramTestSuite;
-
-} // namespace
-
-
--- a/src/contrib/flow-monitor/histogram.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/* -*- 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 <pedro.fortuna@inescporto.pt> <pedro.fortuna@gmail.com>
-//
-
-#ifndef __NS3_HISTOGRAM_H__
-#define __NS3_HISTOGRAM_H__
-
-#include <vector>
-#include <stdint.h>
-#include <ostream>
-
-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<uint32_t> m_histogram;
- double m_binWidth;
-};
-
-
-} // namespace ns3
-
-#endif
-
--- a/src/contrib/flow-monitor/ipv4-flow-classifier.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#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<const Packet> 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<std::map<FiveTuple, FlowId>::iterator, bool> insert
- = m_flowMap.insert (std::pair<FiveTuple, FlowId> (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<FiveTuple, FlowId>::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 << "<Ipv4FlowClassifier>\n";
-
- indent += 2;
- for (std::map<FiveTuple, FlowId>::const_iterator
- iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
- {
- INDENT(indent);
- os << "<Flow flowId=\"" << iter->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 << "</Ipv4FlowClassifier>\n";
-
-#undef INDENT
-}
-
-
-} // namespace ns3
-
--- a/src/contrib/flow-monitor/ipv4-flow-classifier.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#ifndef __IPV4_FLOW_CLASSIFIER_H__
-#define __IPV4_FLOW_CLASSIFIER_H__
-
-#include <stdint.h>
-#include <map>
-
-#include "ns3/ipv4-header.h"
-#include "ns3/flow-classifier.h"
-
-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:
-
- 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<const Packet> 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<FiveTuple, FlowId> 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
-
--- a/src/contrib/flow-monitor/ipv4-flow-probe.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,341 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#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"
-#include "ns3/config.h"
-#include "ns3/flow-id-tag.h"
-
-namespace ns3 {
-
-using namespace std;
-
-NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe");
-
- //////////////////////////////////////
- // Ipv4FlowProbeTag class implementation //
- //////////////////////////////////////
-
-class Ipv4FlowProbeTag : public Tag
-{
-public:
- static TypeId GetTypeId (void);
- virtual TypeId GetInstanceTypeId (void) const;
- virtual uint32_t GetSerializedSize (void) const;
- virtual void Serialize (TagBuffer buf) const;
- virtual void Deserialize (TagBuffer buf);
- virtual void Print (std::ostream &os) const;
- Ipv4FlowProbeTag ();
- Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize);
- void SetFlowId (uint32_t flowId);
- void SetPacketId (uint32_t packetId);
- void SetPacketSize (uint32_t packetSize);
- uint32_t GetFlowId (void) const;
- uint32_t GetPacketId (void) const;
- uint32_t GetPacketSize (void) const;
-private:
- uint32_t m_flowId;
- uint32_t m_packetId;
- uint32_t m_packetSize;
-
-};
-
-TypeId
-Ipv4FlowProbeTag::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
- .SetParent<Tag> ()
- .AddConstructor<Ipv4FlowProbeTag> ()
- ;
- return tid;
-}
-TypeId
-Ipv4FlowProbeTag::GetInstanceTypeId (void) const
-{
- return GetTypeId ();
-}
-uint32_t
-Ipv4FlowProbeTag::GetSerializedSize (void) const
-{
- return 4 + 4 + 4;
-}
-void
-Ipv4FlowProbeTag::Serialize (TagBuffer buf) const
-{
- buf.WriteU32 (m_flowId);
- buf.WriteU32 (m_packetId);
- buf.WriteU32 (m_packetSize);
-}
-void
-Ipv4FlowProbeTag::Deserialize (TagBuffer buf)
-{
- m_flowId = buf.ReadU32 ();
- m_packetId = buf.ReadU32 ();
- m_packetSize = buf.ReadU32 ();
-}
-void
-Ipv4FlowProbeTag::Print (std::ostream &os) const
-{
- os << "FlowId=" << m_flowId;
- os << "PacketId=" << m_packetId;
- os << "PacketSize=" << m_packetSize;
-}
-Ipv4FlowProbeTag::Ipv4FlowProbeTag ()
- : Tag ()
-{}
-
-Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize)
- : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize)
-{}
-
-void
-Ipv4FlowProbeTag::SetFlowId (uint32_t id)
-{
- m_flowId = id;
-}
-void
-Ipv4FlowProbeTag::SetPacketId (uint32_t id)
-{
- m_packetId = id;
-}
-void
-Ipv4FlowProbeTag::SetPacketSize (uint32_t size)
-{
- m_packetSize = size;
-}
-uint32_t
-Ipv4FlowProbeTag::GetFlowId (void) const
-{
- return m_flowId;
-}
-uint32_t
-Ipv4FlowProbeTag::GetPacketId (void) const
-{
- return m_packetId;
-}
-uint32_t
-Ipv4FlowProbeTag::GetPacketSize (void) const
-{
- return m_packetSize;
-}
-
- ////////////////////////////////////////
- // Ipv4FlowProbe class implementation //
- ////////////////////////////////////////
-
-Ipv4FlowProbe::Ipv4FlowProbe (Ptr<FlowMonitor> monitor,
- Ptr<Ipv4FlowClassifier> classifier,
- Ptr<Node> node)
- : FlowProbe (monitor),
- m_classifier (classifier)
-{
- NS_LOG_FUNCTION (this << node->GetId ());
-
- Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
-
- if (!ipv4->TraceConnectWithoutContext ("SendOutgoing",
- MakeCallback (&Ipv4FlowProbe::SendOutgoingLogger, Ptr<Ipv4FlowProbe> (this))))
- {
- NS_FATAL_ERROR ("trace fail");
- }
- if (!ipv4->TraceConnectWithoutContext ("UnicastForward",
- MakeCallback (&Ipv4FlowProbe::ForwardLogger, Ptr<Ipv4FlowProbe> (this))))
- {
- NS_FATAL_ERROR ("trace fail");
- }
- if (!ipv4->TraceConnectWithoutContext ("LocalDeliver",
- MakeCallback (&Ipv4FlowProbe::ForwardUpLogger, Ptr<Ipv4FlowProbe> (this))))
- {
- NS_FATAL_ERROR ("trace fail");
- }
-
- if (!ipv4->TraceConnectWithoutContext ("Drop",
- MakeCallback (&Ipv4FlowProbe::DropLogger, Ptr<Ipv4FlowProbe> (this))))
- {
- NS_FATAL_ERROR ("trace fail");
- }
-
- // code copied from point-to-point-helper.cc
- std::ostringstream oss;
- oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
- Config::ConnectWithoutContext (oss.str (), MakeCallback (&Ipv4FlowProbe::QueueDropLogger, Ptr<Ipv4FlowProbe> (this)));
-}
-
-Ipv4FlowProbe::~Ipv4FlowProbe ()
-{
-}
-
-void
-Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> 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 ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
- << ipHeader << *ipPayload);
- m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
-
- // tag the packet with the flow id and packet id, so that the packet can be identified even
- // when Ipv4Header is not accessible at some non-IPv4 protocol layer
- Ipv4FlowProbeTag fTag (flowId, packetId, size);
- ipPayload->AddPacketTag (fTag);
- }
-}
-
-void
-Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> 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 ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
- m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
- }
-
-}
-
-void
-Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
-{
- FlowId flowId;
- FlowPacketId packetId;
-
- if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
- {
- // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
- Ipv4FlowProbeTag fTag;
-
- // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
- ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
-
- uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
- NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
- m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
- }
-}
-
-void
-Ipv4FlowProbe::DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
- Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, 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))
- {
- // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
- Ipv4FlowProbeTag fTag;
-
- // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
- ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
-
- uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
- NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
- << ", destIp=" << ipHeader.GetDestination () << "); "
- << "HDR: " << ipHeader << " PKT: " << *ipPayload);
-
- DropReason myReason;
-
-
- switch (reason)
- {
- case Ipv4L3Protocol::DROP_TTL_EXPIRED:
- myReason = DROP_TTL_EXPIRE;
- NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
- break;
- case Ipv4L3Protocol::DROP_NO_ROUTE:
- myReason = DROP_NO_ROUTE;
- NS_LOG_DEBUG ("DROP_NO_ROUTE");
- break;
- case Ipv4L3Protocol::DROP_BAD_CHECKSUM:
- myReason = DROP_BAD_CHECKSUM;
- NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
- break;
- case Ipv4L3Protocol::DROP_INTERFACE_DOWN:
- myReason = DROP_INTERFACE_DOWN;
- NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
- break;
- case Ipv4L3Protocol::DROP_ROUTE_ERROR:
- myReason = DROP_ROUTE_ERROR;
- NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
- break;
-
- default:
- myReason = DROP_INVALID_REASON;
- NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
- }
-
- m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
- }
-}
-
-void
-Ipv4FlowProbe::QueueDropLogger (Ptr<const Packet> ipPayload)
-{
- // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
- Ipv4FlowProbeTag fTag;
-
- // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
- bool tagFound;
- tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
- NS_ASSERT_MSG (tagFound, "FlowProbeTag is missing");
-
- FlowId flowId = fTag.GetFlowId ();
- FlowPacketId packetId = fTag.GetPacketId ();
- uint32_t size = fTag.GetPacketSize ();
-
- NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
- << "); ");
-
- m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
-}
-
-} // namespace ns3
-
-
--- a/src/contrib/flow-monitor/ipv4-flow-probe.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,86 +0,0 @@
-/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#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;
-
-/// \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
-{
-
-public:
- Ipv4FlowProbe (Ptr<FlowMonitor> monitor, Ptr<Ipv4FlowClassifier> classifier, Ptr<Node> node);
- virtual ~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,
-
- /// 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,
-
- /// Packet dropped due to queue overflow. Note: only works for
- /// NetDevices that provide a TxQueue attribute of type Queue
- /// with a Drop trace source. It currently works with Csma and
- /// PointToPoint devices, but not with WiFi or WiMax.
- DROP_QUEUE,
-
- DROP_INTERFACE_DOWN, /**< Interface is down so can not send packet */
- DROP_ROUTE_ERROR, /**< Route error */
-
- DROP_INVALID_REASON,
- };
-
-private:
-
- void SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
- void ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
- void ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
- void DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
- Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex);
- void QueueDropLogger (Ptr<const Packet> ipPayload);
-
- Ptr<Ipv4FlowClassifier> m_classifier;
-};
-
-
-} // namespace ns3
-
-#endif
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-classifier.cc Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,42 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#include "flow-classifier.h"
+
+namespace ns3 {
+
+FlowClassifier::FlowClassifier ()
+ :
+ m_lastNewFlowId (0)
+{
+}
+
+FlowClassifier::~FlowClassifier ()
+{}
+
+FlowId
+FlowClassifier::GetNewFlowId ()
+{
+ return ++m_lastNewFlowId;
+}
+
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-classifier.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,66 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#ifndef __FLOW_CLASSIFIER_H__
+#define __FLOW_CLASSIFIER_H__
+
+#include "ns3/simple-ref-count.h"
+#include <ostream>
+
+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 SimpleRefCount<FlowClassifier>
+{
+private:
+ FlowId m_lastNewFlowId;
+
+ FlowClassifier (FlowClassifier const &);
+ FlowClassifier& operator= (FlowClassifier const &);
+
+public:
+
+ FlowClassifier ();
+ virtual ~FlowClassifier ();
+
+ virtual void SerializeToXmlStream (std::ostream &os, int indent) const = 0;
+
+protected:
+ FlowId GetNewFlowId ();
+
+};
+
+
+} // namespace ns3
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-monitor.cc Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,487 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#include "flow-monitor.h"
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+#include "ns3/double.h"
+#include <fstream>
+#include <sstream>
+
+#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<Object> ()
+ .AddConstructor<FlowMonitor> ()
+ .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 <double> ())
+ .AddAttribute ("JitterBinWidth", ("The width used in the jitter histogram."),
+ DoubleValue (0.001),
+ MakeDoubleAccessor (&FlowMonitor::m_jitterBinWidth),
+ MakeDoubleChecker <double> ())
+ .AddAttribute ("PacketSizeBinWidth", ("The width used in the packetSize histogram."),
+ DoubleValue (20),
+ MakeDoubleAccessor (&FlowMonitor::m_packetSizeBinWidth),
+ MakeDoubleChecker <double> ())
+ .AddAttribute ("FlowInterruptionsBinWidth", ("The width used in the flowInterruptions histogram."),
+ DoubleValue (0.250),
+ MakeDoubleAccessor (&FlowMonitor::m_flowInterruptionsBinWidth),
+ MakeDoubleChecker <double> ())
+ .AddAttribute ("FlowInterruptionsMinTime", ("The minimum inter-arrival time that is considered a flow interruption."),
+ TimeValue (Seconds (0.5)),
+ MakeTimeAccessor (&FlowMonitor::m_flowInterruptionsMinTime),
+ MakeTimeChecker ())
+ ;
+ 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<FlowId, FlowStats>::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);
+ ref.flowInterruptionsHistogram.SetDefaultBinWidth (m_flowInterruptionsBinWidth);
+ return ref;
+ }
+ else
+ {
+ return iter->second;
+ }
+}
+
+
+void
+FlowMonitor::ReportFirstTx (Ptr<FlowProbe> 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<FlowProbe> probe, uint32_t flowId, uint32_t packetId, uint32_t packetSize)
+{
+ if (!m_enabled)
+ {
+ return;
+ }
+ std::pair<FlowId, FlowPacketId> 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<FlowProbe> 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;
+ }
+ else
+ {
+ // measure possible flow interruptions
+ Time interArrivalTime = now - stats.timeLastRxPacket;
+ if (interArrivalTime > m_flowInterruptionsMinTime)
+ {
+ stats.flowInterruptionsHistogram.AddValue (interArrivalTime.GetSeconds ());
+ }
+ }
+ 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<FlowProbe> 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<FlowId, FlowMonitor::FlowStats>
+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<FlowId, FlowStats>::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<FlowProbe> probe)
+{
+ m_flowProbes.push_back (probe);
+}
+
+std::vector< Ptr<FlowProbe> >
+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<FlowMonitor> (this));
+}
+
+void
+FlowMonitor::Stop (const Time &time)
+{
+ if (!m_enabled)
+ {
+ return;
+ }
+ Simulator::Cancel (m_stopEvent);
+ m_stopEvent = Simulator::Schedule (time, &FlowMonitor::StopRightNow, Ptr<FlowMonitor> (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<FlowClassifier> classifier)
+{
+ m_classifier = classifier;
+}
+
+void
+FlowMonitor::SerializeToXmlStream (std::ostream &os, int indent, bool enableHistograms, bool enableProbes)
+{
+ CheckForLostPackets ();
+
+ INDENT(indent); os << "<FlowMonitor>\n";
+ indent += 2;
+ INDENT(indent); os << "<FlowStats>\n";
+ indent += 2;
+ for (std::map<FlowId, FlowStats>::const_iterator flowI = m_flowStats.begin ();
+ flowI != m_flowStats.end (); flowI++)
+ {
+
+ INDENT(indent);
+#define ATTRIB(name) << " "#name"=\"" << flowI->second.name << "\""
+ os << "<Flow flowId=\"" << flowI->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 << "<packetsDropped reasonCode=\"" << reasonCode << "\""
+ << " number=\"" << flowI->second.packetsDropped[reasonCode]
+ << "\" />\n";
+ }
+ for (uint32_t reasonCode = 0; reasonCode < flowI->second.bytesDropped.size (); reasonCode++)
+ {
+ INDENT(indent);
+ os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
+ << " bytes=\"" << flowI->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");
+ flowI->second.flowInterruptionsHistogram.SerializeToXmlStream (os, indent, "flowInterruptionsHistogram");
+ }
+ indent -= 2;
+
+ INDENT(indent); os << "</Flow>\n";
+ }
+ indent -= 2;
+ INDENT(indent); os << "</FlowStats>\n";
+
+ m_classifier->SerializeToXmlStream (os, indent);
+
+ if (enableProbes)
+ {
+ INDENT(indent); os << "<FlowProbes>\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 << "</FlowProbes>\n";
+ }
+
+ indent -= 2;
+ INDENT(indent); os << "</FlowMonitor>\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 << "<?xml version=\"1.0\" ?>\n";
+ SerializeToXmlStream (os, 0, enableHistograms, enableProbes);
+ os.close ();
+}
+
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-monitor.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,247 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#ifndef __FLOW_MONITOR_H__
+#define __FLOW_MONITOR_H__
+
+#include <vector>
+#include <map>
+
+#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 {
+
+/// \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;
+
+ /// 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<uint32_t> packetsDropped; // packetsDropped[reasonCode] => number of dropped packets
+
+ /// This attribute also tracks the number of lost bytes. See also
+ /// comment in attribute packetsDropped.
+ std::vector<uint64_t> bytesDropped; // bytesDropped[reasonCode] => number of dropped bytes
+ Histogram flowInterruptionsHistogram; // histogram of durations of flow interruptions
+ };
+
+ // --- basic methods ---
+ static TypeId GetTypeId ();
+ TypeId GetInstanceTypeId () const;
+ FlowMonitor ();
+
+ /// Set the FlowClassifier to be used by the flow monitor.
+ void SetFlowClassifier (Ptr<FlowClassifier> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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<FlowProbe> 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 ---
+ /// 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<FlowId, FlowStats> GetFlowStats () const;
+
+ /// Get a list of all FlowProbe's associated with this FlowMonitor
+ std::vector< Ptr<FlowProbe> > 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);
+
+
+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<FlowId, FlowStats> m_flowStats;
+
+ // (FlowId,PacketId) --> TrackedPacket
+ typedef std::map< std::pair<FlowId, FlowPacketId>, TrackedPacket> TrackedPacketMap;
+ TrackedPacketMap m_trackedPackets;
+ Time m_maxPerHopDelay;
+ std::vector< Ptr<FlowProbe> > m_flowProbes;
+
+ // note: this is needed only for serialization
+ Ptr<FlowClassifier> m_classifier;
+
+ EventId m_startEvent;
+ EventId m_stopEvent;
+ bool m_enabled;
+ double m_delayBinWidth;
+ double m_jitterBinWidth;
+ double m_packetSizeBinWidth;
+ double m_flowInterruptionsBinWidth;
+ Time m_flowInterruptionsMinTime;
+
+ FlowStats& GetStatsForFlow (FlowId flowId);
+ void PeriodicCheckForLostPackets ();
+};
+
+
+} // namespace ns3
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-probe.cc Fri Oct 22 17:18:49 2010 +0100
@@ -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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#include "ns3/flow-probe.h"
+#include "ns3/flow-monitor.h"
+
+namespace ns3 {
+
+
+FlowProbe::~FlowProbe ()
+{
+}
+
+
+FlowProbe::FlowProbe (Ptr<FlowMonitor> 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 << "<FlowProbe index=\"" << index << "\">\n";
+
+ indent += 2;
+
+ for (Stats::const_iterator iter = m_stats.begin (); iter != m_stats.end (); iter++)
+ {
+ INDENT(indent);
+ os << "<FlowStats "
+ << " flowId=\"" << iter->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 << "<packetsDropped reasonCode=\"" << reasonCode << "\""
+ << " number=\"" << iter->second.packetsDropped[reasonCode]
+ << "\" />\n";
+ }
+ for (uint32_t reasonCode = 0; reasonCode < iter->second.bytesDropped.size (); reasonCode++)
+ {
+ INDENT(indent);
+ os << "<bytesDropped reasonCode=\"" << reasonCode << "\""
+ << " bytes=\"" << iter->second.bytesDropped[reasonCode]
+ << "\" />\n";
+ }
+ indent -= 2;
+ INDENT(indent); os << "</FlowStats>\n";
+ }
+ indent -= 2;
+ INDENT(indent); os << "</FlowProbe>\n";
+}
+
+
+
+} // namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/flow-probe.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,91 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#ifndef __FLOW_PROBE_H__
+#define __FLOW_PROBE_H__
+
+#include <map>
+#include <vector>
+
+#include "ns3/simple-ref-count.h"
+#include "ns3/flow-classifier.h"
+#include "ns3/nstime.h"
+
+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 SimpleRefCount<FlowProbe>
+{
+private:
+ FlowProbe (FlowProbe const &);
+ FlowProbe& operator= (FlowProbe const &);
+
+protected:
+
+ FlowProbe (Ptr<FlowMonitor> flowMonitor);
+
+public:
+ virtual ~FlowProbe ();
+
+ struct FlowStats
+ {
+ FlowStats () : delayFromFirstProbeSum (Seconds (0)), bytes (0), packets (0) {}
+
+ /// packetsDropped[reasonCode] => number of dropped packets
+ std::vector<uint32_t> packetsDropped;
+ /// bytesDropped[reasonCode] => number of dropped bytes
+ std::vector<uint64_t> 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;
+ };
+
+ typedef std::map<FlowId, FlowStats> Stats;
+
+ 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;
+
+protected:
+ Ptr<FlowMonitor> m_flowMonitor;
+ Stats m_stats;
+
+};
+
+
+} // namespace ns3
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/histogram.cc Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,214 @@
+/* -*- 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 <pedro.fortuna@inescporto.pt> <pedro.fortuna@gmail.com>
+//
+
+#include <math.h>
+#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 = (uint32_t)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 << "<bin"
+ << " index=\"" << (index) << "\""
+ << " start=\"" << (index*m_binWidth) << "\""
+ << " width=\"" << m_binWidth << "\""
+ << " count=\"" << m_histogram[index] << "\""
+ << " />\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 << "</" << elementName << ">\n";
+#undef INDENT
+}
+
+
+
+
+} // namespace ns3
+
+
+#include "ns3/test.h"
+
+namespace ns3 {
+
+class HistogramTestCase : public ns3::TestCase {
+private:
+public:
+ HistogramTestCase ();
+ virtual bool DoRun (void);
+
+
+};
+
+HistogramTestCase::HistogramTestCase ()
+ : ns3::TestCase ("Histogram")
+{}
+
+
+bool
+HistogramTestCase::DoRun (void)
+{
+ 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_EXPECT_MSG_EQ_TOL (h0.GetBinWidth (0), 3.5, 1e-6, "");
+ NS_TEST_EXPECT_MSG_EQ (h0.GetNBins (), 2, "");
+ NS_TEST_EXPECT_MSG_EQ_TOL (h0.GetBinStart (1), 3.5, 1e-6, "");
+ NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (0), 10, "");
+ NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (1), 5, "");
+ }
+
+ {
+ // Testing bin expansion
+ h0.AddValue (74.3);
+ NS_TEST_EXPECT_MSG_EQ (h0.GetNBins (), 22, "");
+ NS_TEST_EXPECT_MSG_EQ (h0.GetBinCount (21), 1, "");
+ }
+
+ return false;
+}
+
+static class HistogramTestSuite : public TestSuite
+{
+public:
+ HistogramTestSuite ()
+ : TestSuite ("histogram", UNIT)
+ {
+ AddTestCase (new HistogramTestCase ());
+ }
+} g_HistogramTestSuite;
+
+} // namespace
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/histogram.h Fri Oct 22 17:18:49 2010 +0100
@@ -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 <pedro.fortuna@inescporto.pt> <pedro.fortuna@gmail.com>
+//
+
+#ifndef __NS3_HISTOGRAM_H__
+#define __NS3_HISTOGRAM_H__
+
+#include <vector>
+#include <stdint.h>
+#include <ostream>
+
+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<uint32_t> m_histogram;
+ double m_binWidth;
+};
+
+
+} // namespace ns3
+
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/ipv4-flow-classifier.cc Fri Oct 22 17:18:49 2010 +0100
@@ -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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#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<const Packet> 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<std::map<FiveTuple, FlowId>::iterator, bool> insert
+ = m_flowMap.insert (std::pair<FiveTuple, FlowId> (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<FiveTuple, FlowId>::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 << "<Ipv4FlowClassifier>\n";
+
+ indent += 2;
+ for (std::map<FiveTuple, FlowId>::const_iterator
+ iter = m_flowMap.begin (); iter != m_flowMap.end (); iter++)
+ {
+ INDENT(indent);
+ os << "<Flow flowId=\"" << iter->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 << "</Ipv4FlowClassifier>\n";
+
+#undef INDENT
+}
+
+
+} // namespace ns3
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/ipv4-flow-classifier.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,78 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#ifndef __IPV4_FLOW_CLASSIFIER_H__
+#define __IPV4_FLOW_CLASSIFIER_H__
+
+#include <stdint.h>
+#include <map>
+
+#include "ns3/ipv4-header.h"
+#include "ns3/flow-classifier.h"
+
+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:
+
+ 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<const Packet> 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<FiveTuple, FlowId> 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
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/ipv4-flow-probe.cc Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,341 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#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"
+#include "ns3/config.h"
+#include "ns3/flow-id-tag.h"
+
+namespace ns3 {
+
+using namespace std;
+
+NS_LOG_COMPONENT_DEFINE ("Ipv4FlowProbe");
+
+ //////////////////////////////////////
+ // Ipv4FlowProbeTag class implementation //
+ //////////////////////////////////////
+
+class Ipv4FlowProbeTag : public Tag
+{
+public:
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual uint32_t GetSerializedSize (void) const;
+ virtual void Serialize (TagBuffer buf) const;
+ virtual void Deserialize (TagBuffer buf);
+ virtual void Print (std::ostream &os) const;
+ Ipv4FlowProbeTag ();
+ Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize);
+ void SetFlowId (uint32_t flowId);
+ void SetPacketId (uint32_t packetId);
+ void SetPacketSize (uint32_t packetSize);
+ uint32_t GetFlowId (void) const;
+ uint32_t GetPacketId (void) const;
+ uint32_t GetPacketSize (void) const;
+private:
+ uint32_t m_flowId;
+ uint32_t m_packetId;
+ uint32_t m_packetSize;
+
+};
+
+TypeId
+Ipv4FlowProbeTag::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::Ipv4FlowProbeTag")
+ .SetParent<Tag> ()
+ .AddConstructor<Ipv4FlowProbeTag> ()
+ ;
+ return tid;
+}
+TypeId
+Ipv4FlowProbeTag::GetInstanceTypeId (void) const
+{
+ return GetTypeId ();
+}
+uint32_t
+Ipv4FlowProbeTag::GetSerializedSize (void) const
+{
+ return 4 + 4 + 4;
+}
+void
+Ipv4FlowProbeTag::Serialize (TagBuffer buf) const
+{
+ buf.WriteU32 (m_flowId);
+ buf.WriteU32 (m_packetId);
+ buf.WriteU32 (m_packetSize);
+}
+void
+Ipv4FlowProbeTag::Deserialize (TagBuffer buf)
+{
+ m_flowId = buf.ReadU32 ();
+ m_packetId = buf.ReadU32 ();
+ m_packetSize = buf.ReadU32 ();
+}
+void
+Ipv4FlowProbeTag::Print (std::ostream &os) const
+{
+ os << "FlowId=" << m_flowId;
+ os << "PacketId=" << m_packetId;
+ os << "PacketSize=" << m_packetSize;
+}
+Ipv4FlowProbeTag::Ipv4FlowProbeTag ()
+ : Tag ()
+{}
+
+Ipv4FlowProbeTag::Ipv4FlowProbeTag (uint32_t flowId, uint32_t packetId, uint32_t packetSize)
+ : Tag (), m_flowId (flowId), m_packetId (packetId), m_packetSize (packetSize)
+{}
+
+void
+Ipv4FlowProbeTag::SetFlowId (uint32_t id)
+{
+ m_flowId = id;
+}
+void
+Ipv4FlowProbeTag::SetPacketId (uint32_t id)
+{
+ m_packetId = id;
+}
+void
+Ipv4FlowProbeTag::SetPacketSize (uint32_t size)
+{
+ m_packetSize = size;
+}
+uint32_t
+Ipv4FlowProbeTag::GetFlowId (void) const
+{
+ return m_flowId;
+}
+uint32_t
+Ipv4FlowProbeTag::GetPacketId (void) const
+{
+ return m_packetId;
+}
+uint32_t
+Ipv4FlowProbeTag::GetPacketSize (void) const
+{
+ return m_packetSize;
+}
+
+ ////////////////////////////////////////
+ // Ipv4FlowProbe class implementation //
+ ////////////////////////////////////////
+
+Ipv4FlowProbe::Ipv4FlowProbe (Ptr<FlowMonitor> monitor,
+ Ptr<Ipv4FlowClassifier> classifier,
+ Ptr<Node> node)
+ : FlowProbe (monitor),
+ m_classifier (classifier)
+{
+ NS_LOG_FUNCTION (this << node->GetId ());
+
+ Ptr<Ipv4L3Protocol> ipv4 = node->GetObject<Ipv4L3Protocol> ();
+
+ if (!ipv4->TraceConnectWithoutContext ("SendOutgoing",
+ MakeCallback (&Ipv4FlowProbe::SendOutgoingLogger, Ptr<Ipv4FlowProbe> (this))))
+ {
+ NS_FATAL_ERROR ("trace fail");
+ }
+ if (!ipv4->TraceConnectWithoutContext ("UnicastForward",
+ MakeCallback (&Ipv4FlowProbe::ForwardLogger, Ptr<Ipv4FlowProbe> (this))))
+ {
+ NS_FATAL_ERROR ("trace fail");
+ }
+ if (!ipv4->TraceConnectWithoutContext ("LocalDeliver",
+ MakeCallback (&Ipv4FlowProbe::ForwardUpLogger, Ptr<Ipv4FlowProbe> (this))))
+ {
+ NS_FATAL_ERROR ("trace fail");
+ }
+
+ if (!ipv4->TraceConnectWithoutContext ("Drop",
+ MakeCallback (&Ipv4FlowProbe::DropLogger, Ptr<Ipv4FlowProbe> (this))))
+ {
+ NS_FATAL_ERROR ("trace fail");
+ }
+
+ // code copied from point-to-point-helper.cc
+ std::ostringstream oss;
+ oss << "/NodeList/" << node->GetId () << "/DeviceList/*/TxQueue/Drop";
+ Config::ConnectWithoutContext (oss.str (), MakeCallback (&Ipv4FlowProbe::QueueDropLogger, Ptr<Ipv4FlowProbe> (this)));
+}
+
+Ipv4FlowProbe::~Ipv4FlowProbe ()
+{
+}
+
+void
+Ipv4FlowProbe::SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> 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 ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<"); "
+ << ipHeader << *ipPayload);
+ m_flowMonitor->ReportFirstTx (this, flowId, packetId, size);
+
+ // tag the packet with the flow id and packet id, so that the packet can be identified even
+ // when Ipv4Header is not accessible at some non-IPv4 protocol layer
+ Ipv4FlowProbeTag fTag (flowId, packetId, size);
+ ipPayload->AddPacketTag (fTag);
+ }
+}
+
+void
+Ipv4FlowProbe::ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> 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 ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
+ m_flowMonitor->ReportForwarding (this, flowId, packetId, size);
+ }
+
+}
+
+void
+Ipv4FlowProbe::ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface)
+{
+ FlowId flowId;
+ FlowPacketId packetId;
+
+ if (m_classifier->Classify (ipHeader, ipPayload, &flowId, &packetId))
+ {
+ // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+ Ipv4FlowProbeTag fTag;
+
+ // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+ ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+
+ uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
+ NS_LOG_DEBUG ("ReportLastRx ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<");");
+ m_flowMonitor->ReportLastRx (this, flowId, packetId, size);
+ }
+}
+
+void
+Ipv4FlowProbe::DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
+ Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, 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))
+ {
+ // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+ Ipv4FlowProbeTag fTag;
+
+ // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+ ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+
+ uint32_t size = (ipPayload->GetSize () + ipHeader.GetSerializedSize ());
+ NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << reason
+ << ", destIp=" << ipHeader.GetDestination () << "); "
+ << "HDR: " << ipHeader << " PKT: " << *ipPayload);
+
+ DropReason myReason;
+
+
+ switch (reason)
+ {
+ case Ipv4L3Protocol::DROP_TTL_EXPIRED:
+ myReason = DROP_TTL_EXPIRE;
+ NS_LOG_DEBUG ("DROP_TTL_EXPIRE");
+ break;
+ case Ipv4L3Protocol::DROP_NO_ROUTE:
+ myReason = DROP_NO_ROUTE;
+ NS_LOG_DEBUG ("DROP_NO_ROUTE");
+ break;
+ case Ipv4L3Protocol::DROP_BAD_CHECKSUM:
+ myReason = DROP_BAD_CHECKSUM;
+ NS_LOG_DEBUG ("DROP_BAD_CHECKSUM");
+ break;
+ case Ipv4L3Protocol::DROP_INTERFACE_DOWN:
+ myReason = DROP_INTERFACE_DOWN;
+ NS_LOG_DEBUG ("DROP_INTERFACE_DOWN");
+ break;
+ case Ipv4L3Protocol::DROP_ROUTE_ERROR:
+ myReason = DROP_ROUTE_ERROR;
+ NS_LOG_DEBUG ("DROP_ROUTE_ERROR");
+ break;
+
+ default:
+ myReason = DROP_INVALID_REASON;
+ NS_FATAL_ERROR ("Unexpected drop reason code " << reason);
+ }
+
+ m_flowMonitor->ReportDrop (this, flowId, packetId, size, myReason);
+ }
+}
+
+void
+Ipv4FlowProbe::QueueDropLogger (Ptr<const Packet> ipPayload)
+{
+ // remove the tags that are added by Ipv4FlowProbe::SendOutgoingLogger ()
+ Ipv4FlowProbeTag fTag;
+
+ // ConstCast: see http://www.nsnam.org/bugzilla/show_bug.cgi?id=904
+ bool tagFound;
+ tagFound = ConstCast<Packet> (ipPayload)->RemovePacketTag (fTag);
+ NS_ASSERT_MSG (tagFound, "FlowProbeTag is missing");
+
+ FlowId flowId = fTag.GetFlowId ();
+ FlowPacketId packetId = fTag.GetPacketId ();
+ uint32_t size = fTag.GetPacketSize ();
+
+ NS_LOG_DEBUG ("Drop ("<<this<<", "<<flowId<<", "<<packetId<<", "<<size<<", " << DROP_QUEUE
+ << "); ");
+
+ m_flowMonitor->ReportDrop (this, flowId, packetId, size, DROP_QUEUE);
+}
+
+} // namespace ns3
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/flow-monitor/model/ipv4-flow-probe.h Fri Oct 22 17:18:49 2010 +0100
@@ -0,0 +1,86 @@
+/* -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
+//
+
+#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;
+
+/// \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
+{
+
+public:
+ Ipv4FlowProbe (Ptr<FlowMonitor> monitor, Ptr<Ipv4FlowClassifier> classifier, Ptr<Node> node);
+ virtual ~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,
+
+ /// 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,
+
+ /// Packet dropped due to queue overflow. Note: only works for
+ /// NetDevices that provide a TxQueue attribute of type Queue
+ /// with a Drop trace source. It currently works with Csma and
+ /// PointToPoint devices, but not with WiFi or WiMax.
+ DROP_QUEUE,
+
+ DROP_INTERFACE_DOWN, /**< Interface is down so can not send packet */
+ DROP_ROUTE_ERROR, /**< Route error */
+
+ DROP_INVALID_REASON,
+ };
+
+private:
+
+ void SendOutgoingLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
+ void ForwardLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
+ void ForwardUpLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload, uint32_t interface);
+ void DropLogger (const Ipv4Header &ipHeader, Ptr<const Packet> ipPayload,
+ Ipv4L3Protocol::DropReason reason, Ptr<Ipv4> ipv4, uint32_t ifIndex);
+ void QueueDropLogger (Ptr<const Packet> ipPayload);
+
+ Ptr<Ipv4FlowClassifier> m_classifier;
+};
+
+
+} // namespace ns3
+
+#endif
+
--- a/src/contrib/flow-monitor/wscript Fri Oct 22 14:59:56 2010 +0100
+++ b/src/contrib/flow-monitor/wscript Fri Oct 22 17:18:49 2010 +0100
@@ -2,22 +2,24 @@
def build(bld):
obj = bld.create_ns3_module('flow-monitor', ['internet-stack'])
- obj.source = [
+ obj.source = ["model/%s" % s for s in [
'flow-monitor.cc',
'flow-classifier.cc',
'flow-probe.cc',
'ipv4-flow-classifier.cc',
'ipv4-flow-probe.cc',
'histogram.cc',
- ]
+ ]]
+ obj.source.append("helper/flow-monitor-helper.cc")
+
headers = bld.new_task_gen('ns3header')
headers.module = 'flow-monitor'
- headers.source = [
+ headers.source = ["model/%s" % s for s in [
'flow-monitor.h',
'flow-probe.h',
'flow-classifier.h',
'ipv4-flow-classifier.h',
'ipv4-flow-probe.h',
'histogram.h',
- ]
-
+ ]]
+ headers.source.append("helper/flow-monitor-helper.h")
--- a/src/helper/flow-monitor-helper.cc Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-// -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-
-#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<FlowMonitor>
-FlowMonitorHelper::GetMonitor ()
-{
- if (!m_flowMonitor)
- {
- m_flowMonitor = m_monitorFactory.Create<FlowMonitor> ();
- m_flowClassifier = Create<Ipv4FlowClassifier> ();
- m_flowMonitor->SetFlowClassifier (m_flowClassifier);
- }
- return m_flowMonitor;
-}
-
-
-Ptr<FlowClassifier>
-FlowMonitorHelper::GetClassifier ()
-{
- if (!m_flowClassifier)
- {
- m_flowClassifier = Create<Ipv4FlowClassifier> ();
- }
- return m_flowClassifier;
-}
-
-
-Ptr<FlowMonitor>
-FlowMonitorHelper::Install (Ptr<Node> node)
-{
- Ptr<FlowMonitor> monitor = GetMonitor ();
- Ptr<FlowClassifier> classifier = GetClassifier ();
- Ptr<Ipv4FlowProbe> probe = Create<Ipv4FlowProbe> (monitor,
- DynamicCast<Ipv4FlowClassifier> (classifier),
- node);
- return m_flowMonitor;
-}
-
-
-Ptr<FlowMonitor>
-FlowMonitorHelper::Install (NodeContainer nodes)
-{
- for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i)
- {
- Ptr<Node> node = *i;
- if (node->GetObject<Ipv4L3Protocol> ())
- {
- Install (node);
- }
- }
- return m_flowMonitor;
-}
-
-Ptr<FlowMonitor>
-FlowMonitorHelper::InstallAll ()
-{
- for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); ++i)
- {
- Ptr<Node> node = *i;
- if (node->GetObject<Ipv4L3Protocol> ())
- {
- Install (node);
- }
- }
- return m_flowMonitor;
-}
-
-
-} // namespace ns3
--- a/src/helper/flow-monitor-helper.h Fri Oct 22 14:59:56 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-// -*- 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 <gjc@inescporto.pt> <gjcarneiro@gmail.com>
-//
-#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 <string>
-
-namespace ns3 {
-
-class AttributeValue;
-class Ipv4FlowClassifier;
-
-/// \brief Helper to enable IPv4 flow monitoring on a set of Nodes
-class FlowMonitorHelper
-{
-public:
- /// \brief Construct a FlowMonitorHelper class which makes it easier to
- /// configure and use the FlowMonitor
- 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
- /// \param nodes A NodeContainer holding the set of nodes to work with.
- Ptr<FlowMonitor> Install (NodeContainer nodes);
- /// \brief Enable flow monitoring on a single node
- /// \param node A Ptr<Node> to the node on which to enable flow monitoring.
- Ptr<FlowMonitor> Install (Ptr<Node> node);
- /// \brief Enable flow monitoring on all nodes
- Ptr<FlowMonitor> InstallAll ();
-
- /// \brief Retrieve the FlowMonitor object created by the Install* methods
- Ptr<FlowMonitor> GetMonitor ();
-
- /// \brief Retrieve the FlowClassifier object created by the Install* methods
- Ptr<FlowClassifier> GetClassifier ();
-
-private:
- ObjectFactory m_monitorFactory;
- Ptr<FlowMonitor> m_flowMonitor;
- Ptr<FlowClassifier> m_flowClassifier;
-};
-
-} // namespace ns3
-
-
-#endif /* FLOW_MONITOR_HELPER_H */
--- a/src/helper/wscript Fri Oct 22 14:59:56 2010 +0100
+++ b/src/helper/wscript Fri Oct 22 17:18:49 2010 +0100
@@ -42,7 +42,6 @@
'ipv6-list-routing-helper.cc',
'ipv6-routing-helper.cc',
'ping6-helper.cc',
- 'flow-monitor-helper.cc',
'animation-interface.cc',
'canvas-location.cc',
'point-to-point-dumbbell-helper.cc',
@@ -100,7 +99,6 @@
'ipv6-list-routing-helper.h',
'ipv6-routing-helper.h',
'ping6-helper.h',
- 'flow-monitor-helper.h',
'animation-interface.h',
'canvas-location.h',
'point-to-point-dumbbell-helper.h',