diff --git a/examples/routing/dynamic-global-routing.cc b/examples/routing/dynamic-global-routing.cc index a27dacf27..e732343e6 100644 --- a/examples/routing/dynamic-global-routing.cc +++ b/examples/routing/dynamic-global-routing.cc @@ -190,13 +190,14 @@ main (int argc, char *argv[]) apps2.Stop (Seconds (16.0)); - std::ofstream ascii; - ascii.open ("dynamic-global-routing.tr", std::ios_base::binary | std::ios_base::out); + AsciiTraceHelper ascii; + Ptr stream = ascii.CreateFileStream ("dynamic-global-routing.tr", "w"); + p2p.EnableAsciiAll (stream); + csma.EnableAsciiAll (stream); + internet.EnableAsciiAll (stream); + p2p.EnablePcapAll ("dynamic-global-routing"); - PointToPointHelper::EnableAsciiAll (ascii); csma.EnablePcapAll ("dynamic-global-routing", false); - CsmaHelper::EnableAsciiAll (ascii); - InternetStackHelper::EnableAsciiAll (ascii); Ptr n1 = c.Get (1); Ptr ipv41 = n1->GetObject (); diff --git a/examples/routing/mixed-global-routing.cc b/examples/routing/mixed-global-routing.cc index dfeac9f1a..27908896b 100644 --- a/examples/routing/mixed-global-routing.cc +++ b/examples/routing/mixed-global-routing.cc @@ -120,13 +120,13 @@ main (int argc, char *argv[]) apps.Start (Seconds (1.0)); apps.Stop (Seconds (10.0)); - std::ofstream ascii; - ascii.open ("mixed-global-routing.tr"); - p2p.EnablePcapAll ("mixed-global-routing"); - PointToPointHelper::EnableAsciiAll (ascii); - csma.EnablePcapAll ("mixed-global-routing", false); - CsmaHelper::EnableAsciiAll (ascii); + AsciiTraceHelper ascii; + Ptr stream = ascii.CreateFileStream ("mixed-global-routing.tr", "w"); + p2p.EnableAsciiAll (stream); + csma,EnableAsciiAll (stream); + p2p.EnablePcapAll ("mixed-global-routing"); + csma.EnablePcapAll ("mixed-global-routing", false); NS_LOG_INFO ("Run Simulation."); Simulator::Run (); diff --git a/src/devices/emu/emu-net-device.h b/src/devices/emu/emu-net-device.h index 7ec687e76..5ba60b65b 100644 --- a/src/devices/emu/emu-net-device.h +++ b/src/devices/emu/emu-net-device.h @@ -104,6 +104,14 @@ public: */ void SetQueue (Ptr queue); + /** + * Get a copy of the attached Queue. + * + * @returns Ptr to the queue. + */ + Ptr GetQueue(void) const; + + // // Pure virtual methods inherited from NetDevice we must implement. // @@ -218,16 +226,6 @@ private: */ std::string FindCreator (std::string creatorName); - /** - * Get a copy of the attached Queue. - * - * This method is provided for any derived class that may need to get - * direct access to the underlying queue. - * - * @returns Ptr to the queue. - */ - Ptr GetQueue(void) const; - /** * Spin up the device */ diff --git a/src/devices/point-to-point/point-to-point-net-device.h b/src/devices/point-to-point/point-to-point-net-device.h index 9e3eab3cd..666b9dd93 100644 --- a/src/devices/point-to-point/point-to-point-net-device.h +++ b/src/devices/point-to-point/point-to-point-net-device.h @@ -107,6 +107,13 @@ public: */ void SetQueue (Ptr queue); + /** + * Get a copy of the attached Queue. + * + * @returns Ptr to the queue. + */ + Ptr GetQueue(void) const; + /** * Attach a receive ErrorModel to the PointToPointNetDevice. * @@ -261,16 +268,6 @@ private: virtual void DoDispose (void); - /** - * Get a copy of the attached Queue. - * - * This method is provided for any derived class that may need to get - * direct access to the underlying queue. - * - * @returns Ptr to the queue. - */ - Ptr GetQueue(void) const; - private: /** * Calculate the value for the MTU that would result from diff --git a/src/helper/ascii-trace-helper.cc b/src/helper/ascii-trace-helper.cc index e09f37460..4b8470d51 100644 --- a/src/helper/ascii-trace-helper.cc +++ b/src/helper/ascii-trace-helper.cc @@ -74,7 +74,7 @@ AsciiTraceHelper::CreateFileStream (std::string filename, std::string filemode) } std::string -AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool useObjectNames) +AsciiTraceHelper::GetFilenameFromDevice (std::string prefix, Ptr device, bool useObjectNames) { NS_LOG_FUNCTION (prefix << device << useObjectNames); NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string"); @@ -99,7 +99,7 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u } else { - oss << node->GetId (); + oss << "n" << node->GetId (); } oss << "-"; @@ -110,7 +110,7 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u } else { - oss << device->GetIfIndex (); + oss << "d" << device->GetIfIndex (); } oss << ".tr"; @@ -118,11 +118,46 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u return oss.str (); } +std::string +AsciiTraceHelper::GetFilenameFromInterfacePair (std::string prefix, Ptr ipv4, uint32_t interface, bool useObjectNames) +{ + NS_LOG_FUNCTION (prefix << ipv4 << interface << useObjectNames); + NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string"); + + std::ostringstream oss; + oss << prefix << "-"; + + std::string ipv4name; + std::string nodename; + + Ptr node = ipv4->GetObject (); + + if (useObjectNames) + { + ipv4name = Names::FindName (ipv4); + nodename = Names::FindName (node); + } + + if (ipv4name.size ()) + { + oss << ipv4name; + } + else if (nodename.size ()) + { + oss << nodename; + } + else + { + oss << "n" << node->GetId (); + } + + oss << "-i" << interface << ".tr"; + + return oss.str (); +} + // -// The basic default trace sinks. Ascii traces are collected for four -// operations: -// -// Enqueue: +// One of the basic default trace sink sets. Enqueue: // // When a packet has been sent to a device for transmission, the device is // expected to place the packet onto a transmit queue even if it does not @@ -132,7 +167,22 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u // This is typically implemented by hooking the "TxQueue/Enqueue" trace hook // in the device (actually the Queue in the device). // -// Drop: +void +AsciiTraceHelper::DefaultEnqueueSinkWithoutContext (Ptr file, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; +} + +void +AsciiTraceHelper::DefaultEnqueueSinkWithContext (Ptr file, std::string context, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} + +// +// One of the basic default trace sink sets. Drop: // // When a packet has been sent to a device for transmission, the device is // expected to place the packet onto a transmit queue. If this queue is @@ -143,7 +193,22 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u // This is typically implemented by hooking the "TxQueue/Drop" trace hook // in the device (actually the Queue in the device). // -// Dequeue: +void +AsciiTraceHelper::DefaultDropSinkWithoutContext (Ptr file, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; +} + +void +AsciiTraceHelper::DefaultDropSinkWithContext (Ptr file, std::string context, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} + +// +// One of the basic default trace sink sets. Dequeue: // // When a packet has been sent to a device for transmission, the device is // expected to place the packet onto a transmit queue even if it does not @@ -155,7 +220,22 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u // This is typically implemented by hooking the "TxQueue/Dequeue" trace hook // in the device (actually the Queue in the device). // -// Receive: +void +AsciiTraceHelper::DefaultDequeueSinkWithoutContext (Ptr file, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; +} + +void +AsciiTraceHelper::DefaultDequeueSinkWithContext (Ptr file, std::string context, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} + +// +// One of the basic default trace sink sets. Receive: // // When a packet is received by a device for transmission, the device is // expected to trigger this event to indicate the reception has occurred. @@ -164,34 +244,18 @@ AsciiTraceHelper::GetFilename (std::string prefix, Ptr device, bool u // // This is typically implemented by hooking the "MacRx" trace hook in the // device. -// - void -AsciiTraceHelper::DefaultEnqueueSink (Ptr file, Ptr p) -{ - NS_LOG_FUNCTION (file << p); - *file->GetStream () << "+ " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; -} - -void -AsciiTraceHelper::DefaultDropSink (Ptr file, Ptr p) -{ - NS_LOG_FUNCTION (file << p); - *file->GetStream () << "d " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; -} - -void -AsciiTraceHelper::DefaultDequeueSink (Ptr file, Ptr p) -{ - NS_LOG_FUNCTION (file << p); - *file->GetStream () << "- " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; -} - -void -AsciiTraceHelper::DefaultReceiveSink (Ptr file, Ptr p) +AsciiTraceHelper::DefaultReceiveSinkWithoutContext (Ptr file, Ptr p) { NS_LOG_FUNCTION (file << p); *file->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; } +void +AsciiTraceHelper::DefaultReceiveSinkWithContext (Ptr file, std::string context, Ptr p) +{ + NS_LOG_FUNCTION (file << p); + *file->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} + } // namespace ns3 diff --git a/src/helper/ascii-trace-helper.h b/src/helper/ascii-trace-helper.h index cef09398f..8f0b7f76e 100644 --- a/src/helper/ascii-trace-helper.h +++ b/src/helper/ascii-trace-helper.h @@ -19,9 +19,11 @@ #ifndef ASCII_TRACE_HELPER_H #define ASCII_TRACE_HELPER_H +#include "ns3/assert.h" #include "ns3/net-device-container.h" #include "ns3/node-container.h" #include "ns3/simulator.h" +#include "ns3/ipv4.h" #include "ns3/output-stream-object.h" namespace ns3 { @@ -48,9 +50,16 @@ public: /** * @brief Let the ascii trace helper figure out a reasonable filename to use - * for the ascii trace file. + * for an ascii trace file associated with a device. */ - std::string GetFilename (std::string prefix, Ptr device, bool useObjectNames = true); + std::string GetFilenameFromDevice (std::string prefix, Ptr device, bool useObjectNames = true); + + /** + * @brief Let the ascii trace helper figure out a reasonable filename to use + * for an ascii trace file associated with a node. + */ + std::string GetFilenameFromInterfacePair (std::string prefix, Ptr ipv4, + uint32_t interface, bool useObjectNames = true); /** * @brief Create and initialize an output stream object we'll use to write the @@ -75,54 +84,144 @@ public: Ptr CreateFileStream (std::string filename, std::string filemode); /** - * @brief Hook a trace source to the default enqueue operation trace sink + * @brief Hook a trace source to the default enqueue operation trace sink that + * does not accept nor log a trace context. */ - template void HookDefaultEnqueueSink (Ptr object, std::string traceName, Ptr stream); + template + void HookDefaultEnqueueSinkWithoutContext (Ptr object, std::string traceName, Ptr stream); /** - * @brief Hook a trace source to the default drop operation trace sink + * @brief Hook a trace source to the default enqueue operation trace sink that + * does accept and log a trace context. */ - template void HookDefaultDropSink (Ptr object, std::string traceName, Ptr stream); + template + void HookDefaultEnqueueSinkWithContext (Ptr object, std::string traceName, Ptr stream); + + /** + * @brief Hook a trace source to the default drop operation trace sink that + * does not accept nor log a trace context. + */ + template + void HookDefaultDropSinkWithoutContext (Ptr object, std::string traceName, Ptr stream); + + /** + * @brief Hook a trace source to the default drop operation trace sink that + * does accept and log a trace context. + */ + template + void HookDefaultDropSinkWithContext (Ptr object, std::string traceName, Ptr stream); /** * @brief Hook a trace source to the default dequeue operation trace sink + * that does not accept nor log a trace context. */ - template void HookDefaultDequeueSink (Ptr object, std::string traceName, Ptr stream); + template + void HookDefaultDequeueSinkWithoutContext (Ptr object, std::string traceName, Ptr stream); + + /** + * @brief Hook a trace source to the default dequeue operation trace sink + * that does accept and log a trace context. + */ + template + void HookDefaultDequeueSinkWithContext (Ptr object, std::string traceName, Ptr stream); /** * @brief Hook a trace source to the default receive operation trace sink + * that does not accept nor log a trace context. */ - template void HookDefaultReceiveSink (Ptr object, std::string traceName, Ptr stream); + template + void HookDefaultReceiveSinkWithoutContext (Ptr object, std::string traceName, Ptr stream); -private: - static void DefaultEnqueueSink (Ptr file, Ptr p); - static void DefaultDropSink (Ptr file, Ptr p); - static void DefaultDequeueSink (Ptr file, Ptr p); - static void DefaultReceiveSink (Ptr file, Ptr p); + /** + * @brief Hook a trace source to the default receive operation trace sink + * that does accept and log a trace context. + */ + template + void HookDefaultReceiveSinkWithContext (Ptr object, std::string traceName, Ptr stream); + + static void DefaultEnqueueSinkWithoutContext (Ptr file, Ptr p); + static void DefaultEnqueueSinkWithContext (Ptr file, std::string context, Ptr p); + + static void DefaultDropSinkWithoutContext (Ptr file, Ptr p); + static void DefaultDropSinkWithContext (Ptr file, std::string context, Ptr p); + + static void DefaultDequeueSinkWithoutContext (Ptr file, Ptr p); + static void DefaultDequeueSinkWithContext (Ptr file, std::string context, Ptr p); + + static void DefaultReceiveSinkWithoutContext (Ptr file, Ptr p); + static void DefaultReceiveSinkWithContext (Ptr file, std::string context, Ptr p); }; template void -AsciiTraceHelper::HookDefaultEnqueueSink (Ptr object, std::string tracename, Ptr file) +AsciiTraceHelper::HookDefaultEnqueueSinkWithoutContext (Ptr object, std::string tracename, Ptr file) { - object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultEnqueueSink, file)); + bool result = object->TraceConnectWithoutContext (tracename, + MakeBoundCallback (&DefaultEnqueueSinkWithoutContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultEnqueueSinkWithoutContext(): Unable to hook \"" + << tracename << "\""); } template void -AsciiTraceHelper::HookDefaultDropSink (Ptr object, std::string tracename, Ptr file) +AsciiTraceHelper::HookDefaultEnqueueSinkWithContext (Ptr object, std::string tracename, Ptr file) { - object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultDropSink, file)); + std::string context ("XXX"); + bool result = object->TraceConnect (tracename, context, MakeBoundCallback (&DefaultEnqueueSinkWithContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultEnqueueSinkWithContext(): Unable to hook \"" + << tracename << "\""); } template void -AsciiTraceHelper::HookDefaultDequeueSink (Ptr object, std::string tracename, Ptr file) +AsciiTraceHelper::HookDefaultDropSinkWithoutContext (Ptr object, std::string tracename, Ptr file) { - object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultDequeueSink, file)); + bool result = object->TraceConnectWithoutContext (tracename, + MakeBoundCallback (&DefaultDropSinkWithoutContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultDropSinkWithoutContext(): Unable to hook \"" + << tracename << "\""); } template void -AsciiTraceHelper::HookDefaultReceiveSink (Ptr object, std::string tracename, Ptr file) +AsciiTraceHelper::HookDefaultDropSinkWithContext (Ptr object, std::string tracename, Ptr file) { - object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultReceiveSink, file)); + std::string context ("XXX"); + bool result = object->TraceConnect (tracename, context, MakeBoundCallback (&DefaultDropSinkWithContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultDropSinkWithContext(): Unable to hook \"" + << tracename << "\""); +} + +template void +AsciiTraceHelper::HookDefaultDequeueSinkWithoutContext (Ptr object, std::string tracename, Ptr file) +{ + bool result = object->TraceConnectWithoutContext (tracename, + MakeBoundCallback (&DefaultDequeueSinkWithoutContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultDequeueSinkWithoutContext(): Unable to hook \"" + << tracename << "\""); +} + +template void +AsciiTraceHelper::HookDefaultDequeueSinkWithContext (Ptr object, std::string tracename, Ptr file) +{ + std::string context ("XXX"); + bool result = object->TraceConnect (tracename, context, MakeBoundCallback (&DefaultDequeueSinkWithContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultDequeueSinkWithContext(): Unable to hook \"" + << tracename << "\""); +} + +template void +AsciiTraceHelper::HookDefaultReceiveSinkWithoutContext (Ptr object, std::string tracename, Ptr file) +{ + bool result = object->TraceConnectWithoutContext (tracename, + MakeBoundCallback (&DefaultReceiveSinkWithoutContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultReceiveSinkWithoutContext(): Unable to hook \"" + << tracename << "\""); +} + +template void +AsciiTraceHelper::HookDefaultReceiveSinkWithContext (Ptr object, std::string tracename, Ptr file) +{ + std::string context ("XXX"); + bool result = object->TraceConnect (tracename, context, MakeBoundCallback (&DefaultReceiveSinkWithContext, file)); + NS_ASSERT_MSG (result == true, "AsciiTraceHelper::HookDefaultReceiveSinkWithContext(): Unable to hook \"" + << tracename << "\""); } } // namespace ns3 diff --git a/src/helper/ascii-trace-user-helper-for-device.cc b/src/helper/ascii-trace-user-helper-for-device.cc new file mode 100644 index 000000000..339951128 --- /dev/null +++ b/src/helper/ascii-trace-user-helper-for-device.cc @@ -0,0 +1,205 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#include "ns3/abort.h" +#include "ns3/names.h" +#include "ascii-trace-user-helper-for-device.h" + +namespace ns3 { + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (std::string prefix, Ptr nd) +{ + EnableAsciiInternal (Ptr (), prefix, nd); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (Ptr stream, Ptr nd) +{ + EnableAsciiInternal (stream, std::string (), nd); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (std::string prefix, std::string ndName) +{ + EnableAsciiImpl (Ptr (), prefix, ndName); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (Ptr stream, std::string ndName) +{ + EnableAsciiImpl (stream, std::string (), ndName); +} + +// +// Private API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiImpl (Ptr stream, std::string prefix, std::string ndName) +{ + Ptr nd = Names::Find (ndName); + EnableAsciiImpl (stream, prefix, nd); +} + + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (std::string prefix, NetDeviceContainer d) +{ + EnableAsciiImpl (Ptr (), prefix, d); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (Ptr stream, NetDeviceContainer d) +{ + EnableAsciiImpl (stream, std::string (), d); +} + +// +// Private API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiImpl (Ptr stream, std::string prefix, NetDeviceContainer d) +{ + for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) + { + Ptr dev = *i; + EnableAsciiImpl (stream, prefix, dev); + } +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (std::string prefix, NodeContainer n) +{ + EnableAsciiImpl (Ptr (), prefix, n); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (Ptr stream, NodeContainer n) +{ + EnableAsciiImpl (stream, std::string (), n); +} + +// +// Private API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiImpl (Ptr stream, std::string prefix, NodeContainer n) +{ + NetDeviceContainer devs; + for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) + { + Ptr node = *i; + for (uint32_t j = 0; j < node->GetNDevices (); ++j) + { + devs.Add (node->GetDevice (j)); + } + } + EnableAsciiImpl (stream, prefix, devs); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiAll (std::string prefix) +{ + EnableAsciiImpl (Ptr (), prefix, NodeContainer::GetGlobal ()); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiAll (Ptr stream) +{ + EnableAsciiImpl (stream, std::string (), NodeContainer::GetGlobal ()); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (Ptr stream, uint32_t nodeid, uint32_t deviceid) +{ + EnableAsciiImpl (stream, std::string (), nodeid, deviceid); +} + +// +// Public API +// +void +AsciiTraceUserHelperForDevice::EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid) +{ + EnableAsciiImpl (Ptr (), prefix, nodeid, deviceid); +} + +// +// Private API +// +void +AsciiTraceUserHelperForDevice::EnableAsciiImpl ( + Ptr stream, + std::string prefix, + uint32_t nodeid, + uint32_t deviceid) +{ + NodeContainer n = NodeContainer::GetGlobal (); + + for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) + { + Ptr node = *i; + if (node->GetId () != nodeid) + { + continue; + } + + NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), + "AsciiTraceUserHelperForDevice::EnableAscii(): Unknown deviceid = " << deviceid); + + Ptr nd = node->GetDevice (deviceid); + + EnableAsciiImpl (stream, prefix, nd); + return; + } +} + +} // namespace ns3 diff --git a/src/helper/ascii-trace-user-helper-for-device.h b/src/helper/ascii-trace-user-helper-for-device.h new file mode 100644 index 000000000..3e30a8552 --- /dev/null +++ b/src/helper/ascii-trace-user-helper-for-device.h @@ -0,0 +1,221 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#ifndef ASCII_TRACE_USER_HELPER_FOR_DEVICE_H +#define ASCII_TRACE_USER_HELPER_FOR_DEVICE_H + +#include +#include "ns3/net-device-container.h" +#include "ns3/node-container.h" +#include "ns3/output-stream-object.h" + +namespace ns3 { + +/** + * @brief Base class providing common ascii trace operations for helpers + * working with devices. + * + * There are two basic flavors of ascii tracing. The first kind will case a + * trace file to be created for every traced device in the form + * --.tr just like the pcap trace + * helpers would do. Additionally, if the object name service is used to + * define either the node or device, the name will be substituted in the + * file name. This form of ascii tracing does not include a context string + * and makes it easier to determine the source of the event. + * + * The second kind of tracing is more like ns-2 tracing in that there is + * one trace file into which all of the specified events of the specified + * devices are written. This form of ascii tracing does include a context + * string and interleaves the trace hits from all of the devices into a + * single file. + */ +class AsciiTraceUserHelperForDevice +{ +public: + /** + * @brief Enable ascii trace output on the indicated net device. + * @internal + * + * The implementation is expected to use a provided Ptr + * if it is non-null. If the OutputStreamObject is null, the implementation + * is expected to use a provided prefix to construct a new file name for + * each net device using the rules described in the class overview. + * + * If the prefix is provided, there will be one file per net device created. + * In this case, adding a trace context to the file would be pointless, so + * the device implementation is expected to TraceConnectWithoutContext. + * + * If the output stream object is provided, there may be many different + * devices writing to a single file. In this case, the device adding a + * trace context could be important, so the device implementation is + * expected to TraceConnect. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param prefix Filename prefix to use for ascii trace files. + * @param nd Net device for which you want to enable tracing. + */ + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd) = 0; + + /** + * @brief Enable ascii trace output on the indicated net device. + * + * @param prefix Filename prefix to use for ascii files. + * @param nd Net device for which you want to enable tracing. + */ + void EnableAscii (std::string prefix, Ptr nd); + + /** + * @brief Enable ascii trace output on the indicated net device. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param nd Net device for which you want to enable tracing. + */ + void EnableAscii (Ptr stream, Ptr nd); + + /** + * @brief Enable ascii trace output the indicated net device using a device + * previously named using the ns-3 object name service. + * + * @param filename filename prefix to use for ascii files. + * @param ndName The name of the net device in which you want to enable tracing. + */ + void EnableAscii (std::string prefix, std::string ndName); + + /** + * @brief Enable ascii trace output the indicated net device using a device + * previously named using the ns-3 object name service. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param ndName The name of the net device in which you want to enable tracing. + */ + void EnableAscii (Ptr stream, std::string ndName); + + /** + * @brief Enable ascii trace output on each device in the container which is + * of the appropriate type. + * + * @param prefix Filename prefix to use for ascii files. + * @param d container of devices of type ns3::CsmaNetDevice + */ + void EnableAscii (std::string prefix, NetDeviceContainer d); + + /** + * @brief Enable ascii trace output on each device in the container which is + * of the appropriate type. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param d container of devices of type ns3::CsmaNetDevice + */ + void EnableAscii (Ptr stream, NetDeviceContainer d); + + /** + * @brief Enable ascii trace output on each device (which is of the + * appropriate type) in the nodes provided in the container. + * + * \param prefix Filename prefix to use for ascii files. + * \param n container of nodes. + */ + void EnableAscii (std::string prefix, NodeContainer n); + + /** + * @brief Enable ascii trace output on each device (which is of the + * appropriate type) in the nodes provided in the container. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * \param n container of nodes. + */ + void EnableAscii (Ptr stream, NodeContainer n); + + /** + * @brief Enable ascii trace output on each device (which is of the + * appropriate type) in the set of all nodes created in the simulation. + * + * @param prefix Filename prefix to use for ascii files. + */ + void EnableAsciiAll (std::string prefix); + + /** + * @brief Enable ascii trace output on each device (which is of the + * appropriate type) in the set of all nodes created in the simulation. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + */ + void EnableAsciiAll (Ptr stream); + + /** + * @brief Enable ascii trace output on the device specified by a global + * node-id (of a previously created node) and associated device-id. + * + * @param prefix Filename prefix to use when creating ascii trace files + * @param nodeid The node identifier/number of the node on which to enable + * ascii tracing + * @param deviceid The device identifier/index of the device on which to enable + * ascii tracing + */ + void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid); + + /** + * @brief Enable ascii trace output on the device specified by a global + * node-id (of a previously created node) and associated device-id. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param nodeid The node identifier/number of the node on which to enable + * ascii tracing + * @param deviceid The device identifier/index of the device on which to enable + * ascii tracing + */ + void EnableAscii (Ptr stream, uint32_t nodeid, uint32_t deviceid); + +private: + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, uint32_t nodeid, uint32_t deviceid); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, NodeContainer n); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, NetDeviceContainer d); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, std::string ndName); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, Ptr nd); + +}; + +} // namespace ns3 + +#endif // ASCII_USER_HELPER_FOR_DEVICE_H diff --git a/src/helper/ascii-trace-user-helper-for-ipv4.cc b/src/helper/ascii-trace-user-helper-for-ipv4.cc new file mode 100644 index 000000000..f213c32b6 --- /dev/null +++ b/src/helper/ascii-trace-user-helper-for-ipv4.cc @@ -0,0 +1,210 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#include "ns3/abort.h" +#include "ns3/names.h" +#include "ascii-trace-user-helper-for-ipv4.h" + +namespace ns3 { + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (std::string prefix, Ptr ipv4, uint32_t interface) +{ + EnableAsciiInternal (Ptr (), prefix, ipv4, interface); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (Ptr stream, Ptr ipv4, uint32_t interface) +{ + EnableAsciiInternal (stream, std::string (), ipv4, interface); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (std::string prefix, std::string ipv4Name, uint32_t interface) +{ + EnableAsciiImpl (Ptr (), prefix, ipv4Name, interface); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (Ptr stream, std::string ipv4Name, uint32_t interface) +{ + EnableAsciiImpl (stream, std::string (), ipv4Name, interface); +} + +// +// Private API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiImpl ( + Ptr stream, + std::string prefix, + std::string ipv4Name, + uint32_t interface) +{ + Ptr ipv4 = Names::Find (ipv4Name); + EnableAsciiImpl (stream, prefix, ipv4, interface); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (std::string prefix, Ipv4InterfaceContainer c) +{ + EnableAsciiImpl (Ptr (), prefix, c); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (Ptr stream, Ipv4InterfaceContainer c) +{ + EnableAsciiImpl (stream, std::string (), c); +} + +// +// Private API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiImpl (Ptr stream, std::string prefix, Ipv4InterfaceContainer c) +{ + for (Ipv4InterfaceContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + std::pair, uint32_t> pair = *i; + EnableAsciiImpl (stream, prefix, pair.first, pair.second); + } +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (std::string prefix, NodeContainer n) +{ + EnableAsciiImpl (Ptr (), prefix, n); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (Ptr stream, NodeContainer n) +{ + EnableAsciiImpl (stream, std::string (), n); +} + +// +// Private API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiImpl (Ptr stream, std::string prefix, NodeContainer n) +{ + for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) + { + Ptr node = *i; + Ptr ipv4 = node->GetObject (); + if (ipv4) + { + for (uint32_t j = 0; j < ipv4->GetNInterfaces (); ++j) + { + EnableAsciiImpl (stream, prefix, ipv4, j); + } + } + } +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiAll (std::string prefix) +{ + EnableAsciiImpl (Ptr (), prefix, NodeContainer::GetGlobal ()); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiAll (Ptr stream) +{ + EnableAsciiImpl (stream, std::string (), NodeContainer::GetGlobal ()); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (Ptr stream, uint32_t nodeid, uint32_t interface) +{ + EnableAsciiImpl (stream, std::string (), nodeid, interface); +} + +// +// Public API +// +void +AsciiTraceUserHelperForIpv4::EnableAscii (std::string prefix, uint32_t nodeid, uint32_t interface) +{ + EnableAsciiImpl (Ptr (), prefix, nodeid, interface); +} + +// +// Private API +// +void +AsciiTraceUserHelperForIpv4::EnableAsciiImpl ( + Ptr stream, + std::string prefix, + uint32_t nodeid, + uint32_t interface) +{ + NodeContainer n = NodeContainer::GetGlobal (); + + for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) + { + Ptr node = *i; + if (node->GetId () != nodeid) + { + continue; + } + + Ptr ipv4 = node->GetObject (); + if (ipv4) + { + EnableAsciiImpl (stream, prefix, ipv4, interface); + } + + return; + } +} + +} // namespace ns3 diff --git a/src/helper/ascii-trace-user-helper-for-ipv4.h b/src/helper/ascii-trace-user-helper-for-ipv4.h new file mode 100644 index 000000000..5f79b0409 --- /dev/null +++ b/src/helper/ascii-trace-user-helper-for-ipv4.h @@ -0,0 +1,232 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#ifndef ASCII_TRACE_USER_HELPER_FOR_IPV4_H +#define ASCII_TRACE_USER_HELPER_FOR_IPV4_H + +#include +#include "ns3/ipv4-interface-container.h" +#include "ns3/node-container.h" +#include "ns3/output-stream-object.h" + +namespace ns3 { + +/** + * @brief Base class providing common ascii trace operations for helpers + * working with devices. + * + * There are two basic flavors of ascii tracing. The first kind will case a + * trace file to be created for every traced device in the form + * --.tr just like the pcap trace + * helpers would do. Additionally, if the object name service is used to + * define either the node or device, the name will be substituted in the + * file name. This form of ascii tracing does not include a context string + * and makes it easier to determine the source of the event. + * + * The second kind of tracing is more like ns-2 tracing in that there is + * one trace file into which all of the specified events of the specified + * devices are written. This form of ascii tracing does include a context + * string and interleaves the trace hits from all of the devices into a + * single file. + */ +class AsciiTraceUserHelperForIpv4 +{ +public: + /** + * @brief Enable ascii trace output on the indicated Ipv4 and interface pair. + * @internal + * + * The implementation is expected to use a provided Ptr + * if it is non-null. If the OutputStreamObject is null, the implementation + * is expected to use a provided prefix to construct a new file name for + * each net device using the rules described in the class overview. + * + * If the prefix is provided, there will be one file per Ipv4 and interface pair + * created. In this case, adding a trace context to the file would be pointless, + * so the helper implementation is expected to TraceConnectWithoutContext. + * + * If the output stream object is provided, there may be many different Ipv4 + * and interface pairs writing to a single file. In this case, the trace + * context could be important, so the helper implementation is expected to + * TraceConnect. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param prefix Filename prefix to use for ascii trace files. + * @param ipv4 Ptr on which you want to enable tracing. + * @param interface The interface on which you want to enable tracing. + */ + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, + Ptr ipv4, uint32_t interface) = 0; + + /** + * @brief Enable ascii trace output on the indicated Ipv4 and interface pair. + * + * @param prefix Filename prefix to use for ascii files. + * @param ipv4 Ptr on which you want to enable tracing. + * @param interface The interface on which you want to enable tracing. + */ + void EnableAscii (std::string prefix, Ptr ipv4, uint32_t interface); + + /** + * @brief Enable ascii trace output on the indicated Ipv4 and interface pair. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param ipv4 Ptr on which you want to enable tracing. + * @param interface The interface on which you want to enable tracing. + */ + void EnableAscii (Ptr stream, Ptr ipv4, uint32_t interface); + + /** + * @brief Enable ascii trace output the indicated Ipv4 and interface pair + * using an Ipv4 previously named using the ns-3 object name service. + * + * @param filename filename prefix to use for ascii files. + * @param ipv4Name The name of the Ipv4 on which you want to enable tracing. + * @param interface The interface on which you want to enable tracing. + */ + void EnableAscii (std::string prefix, std::string ipv4Name, uint32_t interface); + + /** + * @brief Enable ascii trace output the indicated net device using a device + * previously named using the ns-3 object name service. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param ipv4Name The name of the Ipv4 on which you want to enable tracing. + * @param interface The interface on which you want to enable tracing. + */ + void EnableAscii (Ptr stream, std::string ipv4Name, uint32_t interface); + + /** + * @brief Enable ascii trace output on each Ipv4 and interface pair in the + * container + * + * @param prefix Filename prefix to use for ascii files. + * @param c Ipv4InterfaceContainer of Ipv4 and interface pairs on which to + * enable tracing. + */ + void EnableAscii (std::string prefix, Ipv4InterfaceContainer c); + + /** + * @brief Enable ascii trace output on each device in the container which is + * of the appropriate type. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param c Ipv4InterfaceContainer of Ipv4 and interface pairs on which to + * enable tracing. + */ + void EnableAscii (Ptr stream, Ipv4InterfaceContainer c); + + /** + * @brief Enable ascii trace output on all Ipv4 and interface pairs existing + * in the nodes provided in the container. + * + * \param prefix Filename prefix to use for ascii files. + * \param n container of nodes. + */ + void EnableAscii (std::string prefix, NodeContainer n); + + /** + * @brief Enable ascii trace output on all Ipv4 and interface pairs existing + * in the nodes provided in the container. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * \param n container of nodes. + */ + void EnableAscii (Ptr stream, NodeContainer n); + + /** + * @brief Enable ascii trace output on all Ipv4 and interface pairs existing + * in the set of all nodes created in the simulation. + * + * @param prefix Filename prefix to use for ascii files. + */ + void EnableAsciiAll (std::string prefix); + + /** + * @brief Enable ascii trace output on each device (which is of the + * appropriate type) in the set of all nodes created in the simulation. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + */ + void EnableAsciiAll (Ptr stream); + + /** + * @brief Enable pcap output on the Ipv4 and interface pair specified by a + * global node-id (of a previously created node) and interface. Since there + * can be only one Ipv4 aggregated to a node, the node-id unambiguously + * determines the Ipv4. + * + * @param prefix Filename prefix to use when creating ascii trace files + * @param nodeid The node identifier/number of the node on which to enable + * ascii tracing + * @param interface The device identifier/index of the device on which to enable + * ascii tracing + */ + void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid); + + /** + * @brief Enable pcap output on the Ipv4 and interface pair specified by a + * global node-id (of a previously created node) and interface. Since there + * can be only one Ipv4 aggregated to a node, the node-id unambiguously + * determines the Ipv4. + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param nodeid The node identifier/number of the node on which to enable + * ascii tracing + * @param interface The interface on which you want to enable tracing. + */ + void EnableAscii (Ptr stream, uint32_t nodeid, uint32_t interface); + +private: + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, uint32_t nodeid, uint32_t interface); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, NodeContainer n); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, Ipv4InterfaceContainer c); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, std::string ipv4Name, uint32_t interface); + + /** + * @internal Avoid code duplication. + */ + void EnableAsciiImpl (Ptr stream, std::string prefix, Ptr ipv4, uint32_t interface); + +}; + +} // namespace ns3 + +#endif // ASCII_USER_HELPER_FOR_IPV4_H diff --git a/src/helper/ascii-trace-user-helper.h b/src/helper/ascii-trace-user-helper.h deleted file mode 100644 index 0c174981b..000000000 --- a/src/helper/ascii-trace-user-helper.h +++ /dev/null @@ -1,97 +0,0 @@ -/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ -/* - * Copyright (c) 2010 University of Washington - * - * 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 - */ - -#ifndef ASCII_USER_HELPER_H -#define ASCII_USER_HELPER_H - -#include -#include "ns3/net-device-container.h" -#include "ns3/node-container.h" - -namespace ns3 { - -/** - * \brief Base class providing common ascii trace operations. - */ -class AsciiTraceUserHelper -{ -public: - /** - * @brief Enable ascii trace output on the indicated net device. - * @internal - * - * @param prefix Filename prefix to use for ascii trace files. - * @param nd Net device for which you want to enable tracing. - */ - virtual void EnableAsciiInternal (std::string prefix, Ptr nd) = 0; - - /** - * @brief Enable ascii trace output on the indicated net device. - * - * @param prefix Filename prefix to use for ascii files. - * @param nd Net device for which you want to enable tracing. - */ - void EnableAscii (std::string prefix, Ptr nd); - - /** - * @brief Enable ascii trace output the indicated net device using a device - * previously named using the ns-3 object name service. - * - * @param filename filename prefix to use for ascii files. - * @param ndName The name of the net device in which you want to enable tracing. - */ - void EnableAscii (std::string prefix, std::string ndName); - - /** - * @brief Enable ascii trace output on each device in the container which is - * of the appropriate type. - * - * @param prefix Filename prefix to use for ascii files. - * @param d container of devices of type ns3::CsmaNetDevice - */ - void EnableAscii (std::string prefix, NetDeviceContainer d); - - /** - * @brief Enable ascii trace output on each device (which is of the - * appropriate type) in the nodes provided in the container. - * - * \param prefix Filename prefix to use for ascii files. - * \param n container of nodes. - */ - void EnableAscii (std::string prefix, NodeContainer n); - - /** - * @brief Enable ascii trace output on each device (which is of the - * appropriate type) in the set of all nodes created in the simulation. - * - * @param prefix Filename prefix to use for ascii files. - */ - void EnableAsciiAllXXX (std::string prefix); - - /** - * @brief Enable ascii trace output on the device specified by a global - * node-id (of a previously created node) and associated device-id. - * - * @param prefix Filename prefix to use for ascii files. - */ - void EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid); -}; - -} // namespace ns3 - -#endif // ASCII_USER_HELPER_H diff --git a/src/helper/csma-helper.cc b/src/helper/csma-helper.cc index 5d12a1862..be6cd0518 100644 --- a/src/helper/csma-helper.cc +++ b/src/helper/csma-helper.cc @@ -28,8 +28,6 @@ #include "ns3/config.h" #include "ns3/packet.h" #include "ns3/names.h" -#include "ns3/pcap-writer.h" -#include "ns3/ascii-writer.h" #include "pcap-helper.h" #include "ascii-trace-helper.h" @@ -90,7 +88,7 @@ CsmaHelper::EnablePcapInternal (std::string prefix, Ptr nd, bool prom } PcapHelper pcapHelper; - std::string filename = pcapHelper.GetFilename (prefix, device); + std::string filename = pcapHelper.GetFilenameFromDevice (prefix, device); Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_EN10MB); if (promiscuous) { @@ -103,7 +101,7 @@ CsmaHelper::EnablePcapInternal (std::string prefix, Ptr nd, bool prom } void -CsmaHelper::EnableAsciiInternal (std::string prefix, Ptr nd) +CsmaHelper::EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd) { // // All of the ascii enable functions vector through here including the ones @@ -118,75 +116,75 @@ CsmaHelper::EnableAsciiInternal (std::string prefix, Ptr nd) } // - // Set up an output stream object to deal with private ofstream copy - // constructor and lifetime issues. Let the helper decide the actual - // name of the file given the prefix. + // Our default trace sinks are going to use packet printing, so we have to + // make sure that is turned on. // - AsciiTraceHelper asciiTraceHelper; - std::string filename = asciiTraceHelper.GetFilename (prefix, device); - Ptr stream = asciiTraceHelper.CreateFileStream (filename, "w"); - - // - // The MacRx trace source provides our "r" event. - // - asciiTraceHelper.HookDefaultReceiveSink (device, "MacRx", stream); - - // - // The "+", '-', and 'd' events are driven by trace sources actually in the - // transmit queue. - // - Ptr queue = device->GetQueue (); - asciiTraceHelper.HookDefaultEnqueueSink (queue, "Enqueue", stream); - asciiTraceHelper.HookDefaultDropSink (queue, "Drop", stream); - asciiTraceHelper.HookDefaultDequeueSink (queue, "Dequeue", stream); -} - -void -CsmaHelper::EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid) -{ - Ptr writer = AsciiWriter::Get (os); Packet::EnablePrinting (); + + // + // If we are not provided an OutputStreamObject, we are expected to create + // one using the usual trace filename conventions and do a Hook*WithoutContext + // since there will be one file per context and therefore the context would + // be redundant. + // + if (stream == 0) + { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); + + // + // The MacRx trace source provides our "r" event. + // + asciiTraceHelper.HookDefaultReceiveSinkWithoutContext (device, "MacRx", theStream); + + // + // The "+", '-', and 'd' events are driven by trace sources actually in the + // transmit queue. + // + Ptr queue = device->GetQueue (); + asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext (queue, "Enqueue", theStream); + asciiTraceHelper.HookDefaultDropSinkWithoutContext (queue, "Drop", theStream); + asciiTraceHelper.HookDefaultDequeueSinkWithoutContext (queue, "Dequeue", theStream); + + return; + } + + // + // If we are provided an OutputStreamObject, we are expected to use it, and + // to providd a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with the context. + // + // Note that we are going to use the default trace sinks provided by the + // ascii trace helper. There is actually no AsciiTraceHelper in sight here, + // but the default trace sinks are actually publicly available static + // functions that are always there waiting for just such a case. + // + uint32_t nodeid = nd->GetNode ()->GetId (); + uint32_t deviceid = nd->GetIfIndex (); std::ostringstream oss; - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/MacRx"; - Config::Connect (oss.str (), MakeBoundCallback (&CsmaHelper::AsciiRxEvent, writer)); + + oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/MacRx"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Enqueue"; - Config::Connect (oss.str (), MakeBoundCallback (&CsmaHelper::AsciiEnqueueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Dequeue"; - Config::Connect (oss.str (), MakeBoundCallback (&CsmaHelper::AsciiDequeueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&CsmaHelper::AsciiDropEvent, writer)); -} -void -CsmaHelper::EnableAscii (std::ostream &os, NetDeviceContainer d) -{ - for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) - { - Ptr dev = *i; - EnableAscii (os, dev->GetNode ()->GetId (), dev->GetIfIndex ()); - } -} -void -CsmaHelper::EnableAscii (std::ostream &os, NodeContainer n) -{ - NetDeviceContainer devs; - for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) - { - Ptr node = *i; - for (uint32_t j = 0; j < node->GetNDevices (); ++j) - { - devs.Add (node->GetDevice (j)); - } - } - EnableAscii (os, devs); -} - -void -CsmaHelper::EnableAsciiAll (std::ostream &os) -{ - EnableAscii (os, NodeContainer::GetGlobal ()); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream)); } NetDeviceContainer @@ -272,28 +270,4 @@ CsmaHelper::InstallPriv (Ptr node, Ptr channel) const return device; } -void -CsmaHelper::AsciiEnqueueEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::ENQUEUE, path, packet); -} - -void -CsmaHelper::AsciiDequeueEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::DEQUEUE, path, packet); -} - -void -CsmaHelper::AsciiDropEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::DROP, path, packet); -} - -void -CsmaHelper::AsciiRxEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::RX, path, packet); -} - } // namespace ns3 diff --git a/src/helper/csma-helper.h b/src/helper/csma-helper.h index 0754499e2..8f5397cdb 100644 --- a/src/helper/csma-helper.h +++ b/src/helper/csma-helper.h @@ -28,19 +28,17 @@ #include "ns3/node-container.h" #include "ns3/csma-channel.h" #include "ns3/deprecated.h" - -#include "pcap-user-helper.h" -#include "ascii-trace-user-helper.h" +#include "pcap-user-helper-for-device.h" +#include "ascii-trace-user-helper-for-device.h" namespace ns3 { class Packet; -class AsciiWriter; /** * \brief build a set of CsmaNetDevice objects */ -class CsmaHelper : public PcapUserHelper, public AsciiTraceUserHelper +class CsmaHelper : public PcapUserHelperForDevice, public AsciiTraceUserHelperForDevice { public: /** @@ -86,45 +84,6 @@ public: */ void SetChannelAttribute (std::string n1, const AttributeValue &v1); - /** - * \param os output stream - * \param nodeid the id of the node to generate ascii output for. - * \param deviceid the id of the device to generate ascii output for. - * - * Enable ascii output on the specified deviceid within the - * specified nodeid if it is of type ns3::CsmaNetDevice and dump - * that to the specified stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid); - /** - * \param os output stream - * \param d device container - * - * Enable ascii output on each device which is of the - * ns3::CsmaNetDevice type and which is located in the input - * device container and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NetDeviceContainer d); - /** - * \param os output stream - * \param n node container - * - * Enable ascii output on each device which is of the - * ns3::CsmaNetDevice type and which is located in one - * of the input node and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NodeContainer n); - /** - * \param os output stream - * - * Enable ascii output on each device which is of the - * ns3::CsmaNetDevice type and dump that to the specified - * stdc++ output stream. - */ - static void EnableAsciiAll (std::ostream &os); - /** * This method creates an ns3::CsmaChannel with the attributes configured by * CsmaHelper::SetChannelAttribute, an ns3::CsmaNetDevice with the attributes @@ -253,30 +212,11 @@ private: * NetDevice-specific implementation mechanism for hooking the trace and * writing to the trace file. * - * \param prefix Filename prefix to use for pcap files. + * \param stream The output stream object to use when logging ascii traces. + * \param prefix Filename prefix to use for ascii trace files. * \param nd Net device for which you want to enable tracing. */ - virtual void EnableAsciiInternal (std::string prefix, Ptr nd); - - /* - * \internal - */ - static void AsciiRxEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiEnqueueEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiDequeueEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiDropEvent (Ptr writer, std::string path, Ptr packet); + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd); ObjectFactory m_queueFactory; ObjectFactory m_deviceFactory; diff --git a/src/helper/emu-helper.cc b/src/helper/emu-helper.cc index 0c3e30e71..1029f1dff 100644 --- a/src/helper/emu-helper.cc +++ b/src/helper/emu-helper.cc @@ -24,12 +24,11 @@ #include "ns3/names.h" #include "ns3/queue.h" #include "ns3/emu-net-device.h" -#include "ns3/pcap-writer.h" -#include "ns3/ascii-writer.h" #include "ns3/config.h" #include "ns3/packet.h" #include "pcap-helper.h" +#include "ascii-trace-helper.h" #include "emu-helper.h" NS_LOG_COMPONENT_DEFINE ("EmuHelper"); @@ -82,7 +81,7 @@ EmuHelper::EnablePcapInternal (std::string prefix, Ptr nd, bool promi } PcapHelper pcapHelper; - std::string filename = pcapHelper.GetFilename (prefix, device); + std::string filename = pcapHelper.GetFilenameFromDevice (prefix, device); Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_EN10MB); if (promiscuous) { @@ -95,61 +94,90 @@ EmuHelper::EnablePcapInternal (std::string prefix, Ptr nd, bool promi } void -EmuHelper::EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid) +EmuHelper::EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd) { - NS_LOG_FUNCTION (&os << nodeid << deviceid); - Ptr writer = AsciiWriter::Get (os); + // + // All of the ascii enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type EmuNetDevice. + // + Ptr device = nd->GetObject (); + if (device == 0) + { + NS_LOG_INFO ("EmuHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::EmuNetDevice"); + return; + } + + // + // Our default trace sinks are going to use packet printing, so we have to + // make sure that is turned on. + // Packet::EnablePrinting (); + + // + // If we are not provided an OutputStreamObject, we are expected to create + // one using the usual trace filename conventions and do a Hook*WithoutContext + // since there will be one file per context and therefore the context would + // be redundant. + // + if (stream == 0) + { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); + + // + // The MacRx trace source provides our "r" event. + // + asciiTraceHelper.HookDefaultReceiveSinkWithoutContext (device, "MacRx", theStream); + + // + // The "+", '-', and 'd' events are driven by trace sources actually in the + // transmit queue. + // + Ptr queue = device->GetQueue (); + asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext (queue, "Enqueue", theStream); + asciiTraceHelper.HookDefaultDropSinkWithoutContext (queue, "Drop", theStream); + asciiTraceHelper.HookDefaultDequeueSinkWithoutContext (queue, "Dequeue", theStream); + + return; + } + + // + // If we are provided an OutputStreamObject, we are expected to use it, and + // to providd a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with the context. + // + // Note that we are going to use the default trace sinks provided by the + // ascii trace helper. There is actually no AsciiTraceHelper in sight here, + // but the default trace sinks are actually publicly available static + // functions that are always there waiting for just such a case. + // + uint32_t nodeid = nd->GetNode ()->GetId (); + uint32_t deviceid = nd->GetIfIndex (); std::ostringstream oss; - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::EmuNetDevice/MacRx"; - Config::Connect (oss.str (), MakeBoundCallback (&EmuHelper::AsciiRxEvent, writer)); + oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::EmuNetDevice/MacRx"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream)); oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::EmuNetDevice/TxQueue/Enqueue"; - Config::Connect (oss.str (), MakeBoundCallback (&EmuHelper::AsciiEnqueueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream)); oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::EmuNetDevice/TxQueue/Dequeue"; - Config::Connect (oss.str (), MakeBoundCallback (&EmuHelper::AsciiDequeueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream)); oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::EmuNetDevice/TxQueue/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&EmuHelper::AsciiDropEvent, writer)); -} - -void -EmuHelper::EnableAscii (std::ostream &os, NetDeviceContainer d) -{ - NS_LOG_FUNCTION (&os << &d); - for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) - { - Ptr dev = *i; - EnableAscii (os, dev->GetNode ()->GetId (), dev->GetIfIndex ()); - } -} - -void -EmuHelper::EnableAscii (std::ostream &os, NodeContainer n) -{ - NS_LOG_FUNCTION (&os << &n); - NetDeviceContainer devs; - for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) - { - Ptr node = *i; - for (uint32_t j = 0; j < node->GetNDevices (); ++j) - { - devs.Add (node->GetDevice (j)); - } - } - EnableAscii (os, devs); -} - -void -EmuHelper::EnableAsciiAll (std::ostream &os) -{ - NS_LOG_FUNCTION (&os); - EnableAscii (os, NodeContainer::GetGlobal ()); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream)); } NetDeviceContainer @@ -190,40 +218,4 @@ EmuHelper::InstallPriv (Ptr node) const return device; } -void -EmuHelper::AsciiEnqueueEvent (Ptr writer, - std::string path, - Ptr packet) -{ - NS_LOG_FUNCTION (writer << path << packet); - writer->WritePacket (AsciiWriter::ENQUEUE, path, packet); -} - -void -EmuHelper::AsciiDequeueEvent (Ptr writer, - std::string path, - Ptr packet) -{ - NS_LOG_FUNCTION (writer << path << packet); - writer->WritePacket (AsciiWriter::DEQUEUE, path, packet); -} - -void -EmuHelper::AsciiDropEvent (Ptr writer, - std::string path, - Ptr packet) -{ - NS_LOG_FUNCTION (writer << path << packet); - writer->WritePacket (AsciiWriter::DROP, path, packet); -} - -void -EmuHelper::AsciiRxEvent (Ptr writer, - std::string path, - Ptr packet) -{ - NS_LOG_FUNCTION (writer << path << packet); - writer->WritePacket (AsciiWriter::RX, path, packet); -} - } // namespace ns3 diff --git a/src/helper/emu-helper.h b/src/helper/emu-helper.h index b74a9d6fd..fc1722d68 100644 --- a/src/helper/emu-helper.h +++ b/src/helper/emu-helper.h @@ -28,18 +28,17 @@ #include "ns3/node-container.h" #include "ns3/emu-net-device.h" -#include "pcap-user-helper.h" +#include "pcap-user-helper-for-device.h" +#include "ascii-trace-user-helper-for-device.h" namespace ns3 { class Packet; -class PcapWriter; -class AsciiWriter; /** * \brief build a set of EmuNetDevice objects */ -class EmuHelper : public PcapUserHelper +class EmuHelper : public PcapUserHelperForDevice, public AsciiTraceUserHelperForDevice { public: /* @@ -77,48 +76,6 @@ public: */ void SetAttribute (std::string n1, const AttributeValue &v1); - /** - * \param os output stream - * \param nodeid the id of the node to generate ascii output for. - * \param deviceid the id of the device to generate ascii output for. - * - * Enable ascii output on the specified deviceid within the - * specified nodeid if it is of type ns3::EmuNetDevice and dump - * that to the specified stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid); - - /** - * \param os output stream - * \param d device container - * - * Enable ascii output on each device which is of the - * ns3::EmuNetDevice type and which is located in the input - * device container and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NetDeviceContainer d); - - /** - * \param os output stream - * \param n node container - * - * Enable ascii output on each device which is of the - * ns3::EmuNetDevice type and which is located in one - * of the input node and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NodeContainer n); - - /** - * \param os output stream - * - * Enable ascii output on each device which is of the - * ns3::EmuNetDevice type and dump that to the specified - * stdc++ output stream. - */ - static void EnableAsciiAll (std::ostream &os); - /** * This method creates an ns3::EmuNetDevice with the attributes configured by * EmuHelper::SetDeviceAttribute and then adds the device to the node. @@ -165,25 +122,18 @@ private: */ virtual void EnablePcapInternal (std::string prefix, Ptr nd, bool promiscuous = false); - /* + /** + * \brief Enable ascii trace output on the indicated net device. * \internal + * + * NetDevice-specific implementation mechanism for hooking the trace and + * writing to the trace file. + * + * \param stream The output stream object to use when logging ascii traces. + * \param prefix Filename prefix to use for ascii trace files. + * \param nd Net device for which you want to enable tracing. */ - static void AsciiRxEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiEnqueueEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiDequeueEvent (Ptr writer, std::string path, Ptr packet); - - /* - * \internal - */ - static void AsciiDropEvent (Ptr writer, std::string path, Ptr packet); + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd); ObjectFactory m_queueFactory; ObjectFactory m_deviceFactory; diff --git a/src/helper/internet-stack-helper.cc b/src/helper/internet-stack-helper.cc index 34d8721fc..f9021f252 100644 --- a/src/helper/internet-stack-helper.cc +++ b/src/helper/internet-stack-helper.cc @@ -174,8 +174,10 @@ namespace ns3 { +#if 0 std::vector InternetStackHelper::m_traces; std::string InternetStackHelper::m_pcapBaseFilename; +#endif InternetStackHelper::InternetStackHelper () : m_routing (0), @@ -270,6 +272,7 @@ void InternetStackHelper::SetIpv6StackInstall (bool enable) void InternetStackHelper::Cleanup (void) { +#if 0 uint32_t illegal = std::numeric_limits::max (); for (std::vector::iterator i = m_traces.begin (); @@ -280,6 +283,7 @@ InternetStackHelper::Cleanup (void) i->writer = 0; } m_traces.clear (); +#endif } void @@ -373,6 +377,198 @@ InternetStackHelper::Install (std::string nodeName) const Ptr node = Names::Find (nodeName); Install (node); } + +void +InternetStackHelper::EnablePcapInternal (std::string prefix, Ptr ipv4, uint32_t interface) +{ +#if 0 + // + // We would normally create the pcap file here, but we need to create a file + // for each interface. This is because when the trace sink for Rx and Tx are + // called, we get the packet and an interface ID. We want to group packets + // to/from a given interface id into a pcap file, but we have no knowledge + // here about what interfaces are created. So we have to go with the flow. + // Look for the file creation to happen in the + // + PcapHelper pcapHelper; + std::string filename = pcapHelper.GetFilenameFromNode (prefix, node); + Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_RAW); + + // + // We want to enable Tx and Rx traces on Ipv4L3Protocol if m_ipv4Enabled; and + // we want to enable Tx and Rx traces on Ipv6L3Protocol if m_ipv6Enabled. The + // simple way to do that is to let Config::Connect wander through the global + // node list looking for and then the appropriate protocols and trace + // sources. Since we have the node handy, we can be quicker about it, but it + // takes slightly more work here. + // + if (m_ipv4Enabled) + { + Ptr ipv4L3Protocol = node->GetObject (); + NS_ASSERT_MSG (ipv4L3Protocol, "InternetStackHelper::EnablePcapInternal(): " + "m_ipv4Enabled and ipv4L3Protocol inconsistent"); + + bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Tx", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Tx\""); + + result = ipv4L3Protocol->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Rx\""); + + } + + if (m_ipv6Enabled) + { + Ptr ipv6L3Protocol = node->GetObject (); + NS_FATAL_ERROR_UNLESS (ipv6L3Protocol, "InternetStackHelper::EnablePcapInternal(): " + "m_ipv6Enabled and ipv6L3Protocol inconsistent"); + + bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Tx", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Tx\""); + + result = ipv6L3Protocol->TraceConnectWithoutContext ("Rx", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Rx\""); + + } +#endif +} + + + +#if 0 + // + // We want to enable drop traces on Ipv4L3Protocol and ArpL3Protocol if + // m_ipv4Enabled; and we want to enable the drop trace on Ipv6L3Protocol + // if enabled. The simple way to do that is to let Config::Connect wander + // through the global node list looking for and then the appropriate + // protocols and trace sources. Since we have the node handy, we can be + // quicker about it, but it takes slightly more work here. + // + if (m_ipv4Enabled) + { + Ptr ipv4L3Protocol = node->GetObject (); + NS_ASSERT_MSG (ipv4L3Protocol, "InternetStackHelper::EnablePcapInternal(): " + "m_ipv4Enabled and ipv4L3Protocol inconsistent"); + + bool result = ipv4L3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv4L3Protocol \"Drop\""); + + Ptr arpL3Protocol = node->GetObject (); + NS_ASSERT_MSG (arpL3Protocol, "InternetStackHelper::EnablePcapInternal(): " + "m_ipv4Enabled and arpL3Protocol inconsistent"); + + result = arpL3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect arpL3Protocol \"Drop\""); + } + + if (m_ipv6Enabled) + { + Ptr ipv6L3Protocol = node->GetObject (); + NS_FATAL_ERROR_UNLESS (ipv6L3Protocol, "InternetStackHelper::EnablePcapInternal(): " + "m_ipv6Enabled and ipv6L3Protocol inconsistent"); + + bool result = ipv6L3Protocol->TraceConnectWithoutContext ("Drop", MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "InternetStackHelper::EnablePcapInternal(): Unable to connect ipv6L3Protocol \"Drop\""); + } +#endif + + + +void +InternetStackHelper::EnableAsciiInternal ( + Ptr stream, + std::string prefix, + Ptr ipv4, + uint32_t interface) +{ +#if 0 + // + // All of the ascii enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type CsmaNetDevice. + // + Ptr device = nd->GetObject (); + if (device == 0) + { + NS_LOG_INFO ("CsmaHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::CsmaNetDevice"); + return; + } + + // + // Our default trace sinks are going to use packet printing, so we have to + // make sure that is turned on. + // + Packet::EnablePrinting (); + + // + // If we are not provided an OutputStreamObject, we are expected to create + // one using the usual trace filename conventions and do a Hook*WithoutContext + // since there will be one file per context and therefore the context would + // be redundant. + // + if (stream == 0) + { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); + + // + // The MacRx trace source provides our "r" event. + // + asciiTraceHelper.HookDefaultReceiveSinkWithoutContext (device, "MacRx", theStream); + + // + // The "+", '-', and 'd' events are driven by trace sources actually in the + // transmit queue. + // + Ptr queue = device->GetQueue (); + asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext (queue, "Enqueue", theStream); + asciiTraceHelper.HookDefaultDropSinkWithoutContext (queue, "Drop", theStream); + asciiTraceHelper.HookDefaultDequeueSinkWithoutContext (queue, "Dequeue", theStream); + + return; + } + + // + // If we are provided an OutputStreamObject, we are expected to use it, and + // to providd a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with the context. + // + // Note that we are going to use the default trace sinks provided by the + // ascii trace helper. There is actually no AsciiTraceHelper in sight here, + // but the default trace sinks are actually publicly available static + // functions that are always there waiting for just such a case. + // + uint32_t nodeid = nd->GetNode ()->GetId (); + uint32_t deviceid = nd->GetIfIndex (); + std::ostringstream oss; + + oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/MacRx"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream)); + + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Enqueue"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream)); + + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Dequeue"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream)); + + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::CsmaNetDevice/TxQueue/Drop"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream)); +#endif +} + + + +#if 0 void InternetStackHelper::EnableAscii (std::ostream &os, NodeContainer n) { @@ -497,5 +693,6 @@ InternetStackHelper::AsciiDropEventIpv6 (Ptr writer, std::string pa p->AddHeader (header); writer->WritePacket (AsciiWriter::DROP, path, p); } +#endif } // namespace ns3 diff --git a/src/helper/internet-stack-helper.h b/src/helper/internet-stack-helper.h index 5c9a0ee68..8d9acadac 100644 --- a/src/helper/internet-stack-helper.h +++ b/src/helper/internet-stack-helper.h @@ -26,10 +26,10 @@ #include "ns3/packet.h" #include "ns3/ptr.h" #include "ns3/object-factory.h" -#include "ns3/pcap-writer.h" -#include "ns3/ascii-writer.h" #include "ns3/ipv4-l3-protocol.h" #include "ns3/ipv6-l3-protocol.h" +#include "pcap-user-helper-for-ipv4.h" +#include "ascii-trace-user-helper-for-ipv4.h" namespace ns3 { @@ -39,8 +39,15 @@ class Ipv6RoutingHelper; /** * \brief aggregate IP/TCP/UDP functionality to existing Nodes. + * + * This helper enables pcap and ascii tracing of events in the internet stack + * associated with a node. This is substantially similar to the tracing + * that happens in device helpers, but the important difference is that, well, + * there is no device. This means that the creation of output file names will + * change, and also the user-visible methods will not reference devices and + * therefore the number of trace enable methods is reduced. */ -class InternetStackHelper +class InternetStackHelper : public PcapUserHelperForIpv4, public AsciiTraceUserHelperForIpv4 { public: /** @@ -144,43 +151,6 @@ public: */ void SetTcp (std::string tid, std::string attr, const AttributeValue &val); - /** - * \param os output stream - * \param n node container - * - * Enable ascii output on these drop traces, for each node in the NodeContainer.. - * /NodeList/[i]/$ns3ArpL3Protocol/Drop - * /NodeList/[i]/$ns3Ipv4L3Protocol/Drop - * /NodeList/[i]/$ns3Ipv6L3Protocol/Drop - */ - static void EnableAscii (std::ostream &os, NodeContainer n); - - /** - * \param os output stream - * - * Enable ascii output on these drop traces, for all nodes. - * /NodeList/[i]/$ns3ArpL3Protocol/Drop - * /NodeList/[i]/$ns3Ipv4L3Protocol/Drop - * /NodeList/[i]/$ns3Ipv6L3Protocol/Drop - */ - static void EnableAsciiAll (std::ostream &os); - - /** - * Enable pcap output on each protocol instance which is of the - * ns3::Ipv4L3Protocol or ns3::Ipv6L3Protocol type. Both Tx and - * Rx events will be logged. - * - * \param filename filename prefix to use for pcap files. - * - * \warning If you perform multiple simulations in a single script, - * each iteration of the simulation will result in the trace files - * being overwritten. We don't attempt to anticipate what a user - * might actually want to do, so we leave it up to them. If you want - * to save any particular data, do so manually at inter-simulation - * time. - */ - static void EnablePcapAll (std::string filename); - /** * \brief Enable/disable IPv4 stack install. * \param enable enable state @@ -194,6 +164,28 @@ public: void SetIpv6StackInstall (bool enable); private: + /** + * @brief Enable pcap output the indicated Ipv4 and interface pair. + * @internal + * + * @param prefix Filename prefix to use for pcap files. + * @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing. + * @param interface Interface ID on the Ipv4 on which you want to enable tracing. + */ + virtual void EnablePcapInternal (std::string prefix, Ptr ipv4, uint32_t interface); + + /** + * @brief Enable ascii trace output on the indicated Ipv4 and interface pair. + * @internal + * + * @param stream An OutputStreamObject representing an existing file to use + * when writing trace data. + * @param prefix Filename prefix to use for ascii trace files. + * @param ipv4 Ptr to the Ipv4 interface on which you want to enable tracing. + * @param interface Interface ID on the Ipv4 on which you want to enable tracing. + */ + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr ipv4, uint32_t interface); + void Initialize (void); ObjectFactory m_tcpFactory; const Ipv4RoutingHelper *m_routing; @@ -214,6 +206,7 @@ private: */ static void Cleanup (void); +#if 0 /** * \internal */ @@ -261,6 +254,7 @@ private: static uint32_t GetNodeIndex (std::string context); static std::vector m_traces; +#endif /** * \brief IPv4 install state (enabled/disabled) ? diff --git a/src/helper/ipv4-interface-container.cc b/src/helper/ipv4-interface-container.cc index 31e4e57c8..b12b05713 100644 --- a/src/helper/ipv4-interface-container.cc +++ b/src/helper/ipv4-interface-container.cc @@ -16,6 +16,18 @@ Ipv4InterfaceContainer::Add (Ipv4InterfaceContainer other) } } +Ipv4InterfaceContainer::Iterator +Ipv4InterfaceContainer::Begin (void) const +{ + return m_interfaces.begin (); +} + +Ipv4InterfaceContainer::Iterator +Ipv4InterfaceContainer::End (void) const +{ + return m_interfaces.end (); +} + uint32_t Ipv4InterfaceContainer::GetN (void) const { diff --git a/src/helper/ipv4-interface-container.h b/src/helper/ipv4-interface-container.h index f031a3a31..f892e613f 100644 --- a/src/helper/ipv4-interface-container.h +++ b/src/helper/ipv4-interface-container.h @@ -32,6 +32,8 @@ namespace ns3 { class Ipv4InterfaceContainer { public: + typedef std::vector, uint32_t> >::const_iterator Iterator; + /** * Create an empty Ipv4InterfaceContainer. */ @@ -43,9 +45,70 @@ public: */ void Add (Ipv4InterfaceContainer other); + /** + * \brief Get an iterator which refers to the first pair in the + * container. + * + * Pairs can be retrieved from the container in two ways. First, + * directly by an index into the container, and second, using an iterator. + * This method is used in the iterator method and is typically used in a + * for-loop to run through the pairs + * + * \code + * Ipv4InterfaceContainer::Iterator i; + * for (i = container.Begin (); i != container.End (); ++i) + * { + * std::pair, uint32_t> pair = *i; + * method (pair.first, pair.second); // use the pair + * } + * \endcode + * + * \returns an iterator which refers to the first pair in the container. + */ + Iterator Begin (void) const; + + /** + * \brief Get an iterator which indicates past-the-last Node in the + * container. + * + * Nodes can be retrieved from the container in two ways. First, + * directly by an index into the container, and second, using an iterator. + * This method is used in the iterator method and is typically used in a + * for-loop to run through the Nodes + * + * \code + * NodeContainer::Iterator i; + * for (i = container.Begin (); i != container.End (); ++i) + * { + * std::pair, uint32_t> pair = *i; + * method (pair.first, pair.second); // use the pair + * } + * \endcode + * + * \returns an iterator which indicates an ending condition for a loop. + */ + Iterator End (void) const; + /** * \returns the number of Ptr and interface pairs stored in this * Ipv4InterfaceContainer. + * + * Pairs can be retrieved from the container in two ways. First, + * directly by an index into the container, and second, using an iterator. + * This method is used in the direct method and is typically used to + * define an ending condition in a for-loop that runs through the stored + * Nodes + * + * \code + * uint32_t nNodes = container.GetN (); + * for (uint32_t i = 0 i < nNodes; ++i) + * { + * std::pair, uint32_t> pair = container.Get (i); + * method (pair.first, pair.second); // use the pair + * } + * \endcode + * + * \returns the number of Ptr stored in this container. */ uint32_t GetN (void) const; @@ -61,7 +124,6 @@ public: */ Ipv4Address GetAddress (uint32_t i, uint32_t j = 0) const; - void SetMetric (uint32_t i, uint16_t metric); /** diff --git a/src/helper/node-container.h b/src/helper/node-container.h index 7a07f5e0b..adb6f2498 100644 --- a/src/helper/node-container.h +++ b/src/helper/node-container.h @@ -189,10 +189,10 @@ public: * Nodes * * \code - * uint32_t nNodes = continer.GetN (); + * uint32_t nNodes = container.GetN (); * for (uint32_t i = 0 i < nNodes; ++i) * { - * Ptr p = continer.Get (i) + * Ptr p = container.Get (i) * i->method (); // some Node method * } * \endcode diff --git a/src/helper/pcap-helper.cc b/src/helper/pcap-helper.cc index e7aeb8a24..e30e5793c 100644 --- a/src/helper/pcap-helper.cc +++ b/src/helper/pcap-helper.cc @@ -77,7 +77,7 @@ PcapHelper::CreateFile ( } std::string -PcapHelper::GetFilename (std::string prefix, Ptr device, bool useObjectNames) +PcapHelper::GetFilenameFromDevice (std::string prefix, Ptr device, bool useObjectNames) { NS_LOG_FUNCTION (prefix << device << useObjectNames); NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string"); @@ -102,7 +102,7 @@ PcapHelper::GetFilename (std::string prefix, Ptr device, bool useObje } else { - oss << node->GetId (); + oss << "n" << node->GetId (); } oss << "-"; @@ -113,7 +113,7 @@ PcapHelper::GetFilename (std::string prefix, Ptr device, bool useObje } else { - oss << device->GetIfIndex (); + oss << "d" << device->GetIfIndex (); } oss << ".pcap"; @@ -121,6 +121,44 @@ PcapHelper::GetFilename (std::string prefix, Ptr device, bool useObje return oss.str (); } +std::string +PcapHelper::GetFilenameFromInterfacePair (std::string prefix, Ptr ipv4, uint32_t interface, bool useObjectNames) +{ + NS_LOG_FUNCTION (prefix << ipv4 << interface << useObjectNames); + NS_ABORT_MSG_UNLESS (prefix.size (), "Empty prefix string"); + + std::ostringstream oss; + oss << prefix << "-"; + + std::string ipv4name; + std::string nodename; + + Ptr node = ipv4->GetObject (); + + if (useObjectNames) + { + ipv4name = Names::FindName (ipv4); + nodename = Names::FindName (node); + } + + if (ipv4name.size ()) + { + oss << ipv4name; + } + else if (nodename.size ()) + { + oss << nodename; + } + else + { + oss << "n" << node->GetId (); + } + + oss << "-i" << interface << ".pcap"; + + return oss.str (); +} + // // The basic default trace sink. This one just writes the packet to the pcap // file which is good enough for most kinds of captures. diff --git a/src/helper/pcap-helper.h b/src/helper/pcap-helper.h index 52890f04d..1b30406e7 100644 --- a/src/helper/pcap-helper.h +++ b/src/helper/pcap-helper.h @@ -19,10 +19,12 @@ #ifndef PCAP_HELPER_H #define PCAP_HELPER_H +#include "ns3/assert.h" #include "ns3/net-device-container.h" #include "ns3/node-container.h" #include "ns3/simulator.h" #include "ns3/pcap-file-object.h" +#include "ns3/ipv4.h" namespace ns3 { @@ -45,6 +47,7 @@ public: enum {DLT_NULL = 0}; enum {DLT_EN10MB = 1}; enum {DLT_PPP = 9}; + enum {DLT_RAW = 101}; enum {DLT_IEEE802_11 = 105}; enum {DLT_PRISM_HEADER = 119}; enum {DLT_IEEE802_11_RADIO = 127}; @@ -60,10 +63,17 @@ public: ~PcapHelper (); /** - * @brief Let the pcap helper figure out a reasonable filename to use for the - * pcap file. + * @brief Let the pcap helper figure out a reasonable filename to use for a + * pcap file associated with a device. */ - std::string GetFilename (std::string prefix, Ptr device, bool useObjectNames = true); + std::string GetFilenameFromDevice (std::string prefix, Ptr device, bool useObjectNames = true); + + /** + * @brief Let the pcap helper figure out a reasonable filename to use for the + * pcap file associated with a node. + */ + std::string GetFilenameFromInterfacePair (std::string prefix, Ptr ipv4, + uint32_t interface, bool useObjectNames = true); /** * @brief Create and initialize a pcap file. @@ -82,7 +92,8 @@ private: template void PcapHelper::HookDefaultSink (Ptr object, std::string tracename, Ptr file) { - object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultSink, file)); + bool result = object->TraceConnectWithoutContext (tracename.c_str (), MakeBoundCallback (&DefaultSink, file)); + NS_ASSERT_MSG (result == true, "PcapHelper::HookDefaultSink(): Unable to hook \"" << tracename << "\""); } } // namespace ns3 diff --git a/src/helper/pcap-user-helper.cc b/src/helper/pcap-user-helper-for-device.cc similarity index 74% rename from src/helper/pcap-user-helper.cc rename to src/helper/pcap-user-helper-for-device.cc index 605bfedc2..ea7fc39e8 100644 --- a/src/helper/pcap-user-helper.cc +++ b/src/helper/pcap-user-helper-for-device.cc @@ -18,25 +18,25 @@ #include "ns3/abort.h" #include "ns3/names.h" -#include "pcap-user-helper.h" +#include "pcap-user-helper-for-device.h" namespace ns3 { void -PcapUserHelper::EnablePcap (std::string prefix, Ptr nd, bool promiscuous) +PcapUserHelperForDevice::EnablePcap (std::string prefix, Ptr nd, bool promiscuous) { EnablePcapInternal (prefix, nd, promiscuous); } void -PcapUserHelper::EnablePcap (std::string prefix, std::string ndName, bool promiscuous) +PcapUserHelperForDevice::EnablePcap (std::string prefix, std::string ndName, bool promiscuous) { Ptr nd = Names::Find (ndName); EnablePcap (prefix, nd, promiscuous); } void -PcapUserHelper::EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous) +PcapUserHelperForDevice::EnablePcap (std::string prefix, NetDeviceContainer d, bool promiscuous) { for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) { @@ -46,7 +46,7 @@ PcapUserHelper::EnablePcap (std::string prefix, NetDeviceContainer d, bool promi } void -PcapUserHelper::EnablePcap (std::string prefix, NodeContainer n, bool promiscuous) +PcapUserHelperForDevice::EnablePcap (std::string prefix, NodeContainer n, bool promiscuous) { NetDeviceContainer devs; for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) @@ -61,13 +61,13 @@ PcapUserHelper::EnablePcap (std::string prefix, NodeContainer n, bool promiscuou } void -PcapUserHelper::EnablePcapAll (std::string prefix, bool promiscuous) +PcapUserHelperForDevice::EnablePcapAll (std::string prefix, bool promiscuous) { EnablePcap (prefix, NodeContainer::GetGlobal (), promiscuous); } void -PcapUserHelper::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous) +PcapUserHelperForDevice::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t deviceid, bool promiscuous) { NodeContainer n = NodeContainer::GetGlobal (); @@ -79,9 +79,9 @@ PcapUserHelper::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t device continue; } - NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), "PcapUserHelper::EnablePcap(): Unknown deviceid = " << deviceid); + NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), "PcapUserHelperForDevice::EnablePcap(): Unknown deviceid = " + << deviceid); Ptr nd = node->GetDevice (deviceid); - EnablePcap (prefix, nd, promiscuous); return; } diff --git a/src/helper/pcap-user-helper.h b/src/helper/pcap-user-helper-for-device.h similarity index 96% rename from src/helper/pcap-user-helper.h rename to src/helper/pcap-user-helper-for-device.h index 7f78207f4..32626c584 100644 --- a/src/helper/pcap-user-helper.h +++ b/src/helper/pcap-user-helper-for-device.h @@ -26,9 +26,10 @@ namespace ns3 { /** - * \brief Base class providing common pcap operations. + * \brief Base class providing common user-level pcap operations for helpers + * representing net devices. */ -class PcapUserHelper +class PcapUserHelperForDevice { public: /** diff --git a/src/helper/ascii-trace-user-helper.cc b/src/helper/pcap-user-helper-for-ipv4.cc similarity index 51% rename from src/helper/ascii-trace-user-helper.cc rename to src/helper/pcap-user-helper-for-ipv4.cc index 8f8789441..489d8ee2d 100644 --- a/src/helper/ascii-trace-user-helper.cc +++ b/src/helper/pcap-user-helper-for-ipv4.cc @@ -18,56 +18,58 @@ #include "ns3/abort.h" #include "ns3/names.h" -#include "ascii-trace-user-helper.h" +#include "pcap-user-helper-for-ipv4.h" namespace ns3 { void -AsciiTraceUserHelper::EnableAscii (std::string prefix, Ptr nd) +PcapUserHelperForIpv4::EnablePcap (std::string prefix, Ptr ipv4, uint32_t interface) { - EnableAsciiInternal (prefix, nd); + EnablePcapInternal (prefix, ipv4, interface); } void -AsciiTraceUserHelper::EnableAscii (std::string prefix, std::string ndName) +PcapUserHelperForIpv4::EnablePcap (std::string prefix, std::string ipv4Name, uint32_t interface) { - Ptr nd = Names::Find (ndName); - EnableAscii (prefix, nd); + Ptr ipv4 = Names::Find (ipv4Name); + EnablePcap (prefix, ipv4, interface); } void -AsciiTraceUserHelper::EnableAscii (std::string prefix, NetDeviceContainer d) +PcapUserHelperForIpv4::EnablePcap (std::string prefix, Ipv4InterfaceContainer c) { - for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) + for (Ipv4InterfaceContainer::Iterator i = c.Begin (); i != c.End (); ++i) { - Ptr dev = *i; - EnableAscii (prefix, dev); + std::pair, uint32_t> pair = *i; + EnablePcap (prefix, pair.first, pair.second); } } void -AsciiTraceUserHelper::EnableAscii (std::string prefix, NodeContainer n) +PcapUserHelperForIpv4::EnablePcap (std::string prefix, NodeContainer n) { - NetDeviceContainer devs; for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) { Ptr node = *i; - for (uint32_t j = 0; j < node->GetNDevices (); ++j) + Ptr ipv4 = node->GetObject (); + if (ipv4) { - devs.Add (node->GetDevice (j)); + for (uint32_t j = 0; j < ipv4->GetNInterfaces (); ++j) + { + EnablePcap (prefix, ipv4, j); + } } } - EnableAscii (prefix, devs); } void -AsciiTraceUserHelper::EnableAsciiAllXXX (std::string prefix) +PcapUserHelperForIpv4::EnablePcapAll (std::string prefix) { - EnableAscii (prefix, NodeContainer::GetGlobal ()); + EnablePcap (prefix, NodeContainer::GetGlobal ()); } void -AsciiTraceUserHelper::EnableAscii (std::string prefix, uint32_t nodeid, uint32_t deviceid) +PcapUserHelperForIpv4::EnablePcap (std::string prefix, uint32_t nodeid, uint32_t interface) { NodeContainer n = NodeContainer::GetGlobal (); @@ -79,12 +81,11 @@ AsciiTraceUserHelper::EnableAscii (std::string prefix, uint32_t nodeid, uint32_t continue; } - NS_ABORT_MSG_IF (deviceid >= node->GetNDevices (), - "AsciiTraceUserHelper::EnableAscii(): Unknown deviceid = " << deviceid); - - Ptr nd = node->GetDevice (deviceid); - - EnableAscii (prefix, nd); + Ptr ipv4 = node->GetObject (); + if (ipv4) + { + EnablePcap (prefix, ipv4, interface); + } return; } } diff --git a/src/helper/pcap-user-helper-for-ipv4.h b/src/helper/pcap-user-helper-for-ipv4.h new file mode 100644 index 000000000..83ef004cf --- /dev/null +++ b/src/helper/pcap-user-helper-for-ipv4.h @@ -0,0 +1,102 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2010 University of Washington + * + * 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 + */ + +#ifndef PCAP_USER_HELPER_FOR_IPV4_H +#define PCAP_USER_HELPER_FOR_IPV4_H + +#include +#include "ns3/ipv4-interface-container.h" +#include "ns3/node-container.h" + +namespace ns3 { + +/** + * \brief Base class providing common user-level pcap operations for helpers + * representing IPv4 protocols . + */ +class PcapUserHelperForIpv4 +{ +public: + /** + * @brief Enable pcap output the indicated Ipv4 and interface pair. + * @internal + * + * @param prefix Filename prefix to use for pcap files. + * @param ipv4 Ptr on which you want to enable tracing. + * @param interface Interface on ipv4 on which you want to enable tracing. + */ + virtual void EnablePcapInternal (std::string prefix, Ptr ipv4, uint32_t interface) = 0; + + /** + * @brief Enable pcap output the indicated Ipv4 and interface pair. + * + * @param prefix Filename prefix to use for pcap files. + * @param ipv4 Ptr on which you want to enable tracing. + * @param interface Interface on ipv4 on which you want to enable tracing. + */ + void EnablePcap (std::string prefix, Ptr ipv4, uint32_t interface); + + /** + * @brief Enable pcap output the indicated Ipv4 and interface pair using a + * Ptr previously named using the ns-3 object name service. + * + * @param filename filename prefix to use for pcap files. + * @param ipv4Name Name of the Ptr on which you want to enable tracing. + * @param interface Interface on ipv4 on which you want to enable tracing. + */ + void EnablePcap (std::string prefix, std::string ipv4Name, uint32_t interface); + + /** + * @brief Enable pcap output on each Ipv4 and interface pair in the container. + * + * @param prefix Filename prefix to use for pcap files. + * @param c Ipv4InterfaceContainer of Ipv4 and interface pairs + */ + void EnablePcap (std::string prefix, Ipv4InterfaceContainer c); + + /** + * @brief Enable pcap output on all Ipv4 and interface pairs existing in the + * nodes provided in the container. + * + * \param prefix Filename prefix to use for pcap files. + * \param n container of nodes. + */ + void EnablePcap (std::string prefix, NodeContainer n); + + /** + * @brief Enable pcap output on all Ipv4 and interface pairs existing in the + * set of all nodes created in the simulation. + * + * @param prefix Filename prefix to use for pcap files. + */ + void EnablePcapAll (std::string prefix); + + /** + * @brief Enable pcap output on the Ipv4 and interface pair specified by a + * global node-id (of a previously created node) and interface. Since there + * can be only one Ipv4 aggregated to a node, the node-id unambiguously + * determines the Ipv4. + * + * @param prefix Filename prefix to use for pcap files. + */ + void EnablePcap (std::string prefix, uint32_t nodeid, uint32_t interface); +}; + +} // namespace ns3 + +#endif // PCAP_USER_HELPER_FOR_IPV4_H diff --git a/src/helper/point-to-point-helper.cc b/src/helper/point-to-point-helper.cc index 4f73ad939..2e342a959 100644 --- a/src/helper/point-to-point-helper.cc +++ b/src/helper/point-to-point-helper.cc @@ -27,10 +27,9 @@ #include "ns3/config.h" #include "ns3/packet.h" #include "ns3/names.h" -#include "ns3/pcap-writer.h" -#include "ns3/ascii-writer.h" #include "pcap-helper.h" +#include "ascii-trace-helper.h" #include "point-to-point-helper.h" NS_LOG_COMPONENT_DEFINE ("PointToPointHelper"); @@ -86,59 +85,97 @@ PointToPointHelper::EnablePcapInternal (std::string prefix, Ptr nd, b } PcapHelper pcapHelper; - std::string filename = pcapHelper.GetFilename (prefix, device); + std::string filename = pcapHelper.GetFilenameFromDevice (prefix, device); Ptr file = pcapHelper.CreateFile (filename, "w", PcapHelper::DLT_PPP); pcapHelper.HookDefaultSink (device, "PromiscSniffer", file); } void -PointToPointHelper::EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid) +PointToPointHelper::EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd) { - Ptr writer = AsciiWriter::Get (os); + // + // All of the ascii enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type PointToPointNetDevice. + // + Ptr device = nd->GetObject (); + if (device == 0) + { + NS_LOG_INFO ("PointToPointHelper::EnableAsciiInternal(): Device " << device << + " not of type ns3::PointToPointNetDevice"); + return; + } + + // + // Our default trace sinks are going to use packet printing, so we have to + // make sure that is turned on. + // Packet::EnablePrinting (); + + // + // If we are not provided an OutputStreamObject, we are expected to create + // one using the usual trace filename conventions and do a Hook*WithoutContext + // since there will be one file per context and therefore the context would + // be redundant. + // + if (stream == 0) + { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); + + // + // The MacRx trace source provides our "r" event. + // + asciiTraceHelper.HookDefaultReceiveSinkWithoutContext (device, "MacRx", theStream); + + // + // The "+", '-', and 'd' events are driven by trace sources actually in the + // transmit queue. + // + Ptr queue = device->GetQueue (); + asciiTraceHelper.HookDefaultEnqueueSinkWithoutContext (queue, "Enqueue", theStream); + asciiTraceHelper.HookDefaultDropSinkWithoutContext (queue, "Drop", theStream); + asciiTraceHelper.HookDefaultDequeueSinkWithoutContext (queue, "Dequeue", theStream); + + return; + } + + // + // If we are provided an OutputStreamObject, we are expected to use it, and + // to providd a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with the context. + // + // Note that we are going to use the default trace sinks provided by the + // ascii trace helper. There is actually no AsciiTraceHelper in sight here, + // but the default trace sinks are actually publicly available static + // functions that are always there waiting for just such a case. + // + uint32_t nodeid = nd->GetNode ()->GetId (); + uint32_t deviceid = nd->GetIfIndex (); std::ostringstream oss; - oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/MacRx"; - Config::Connect (oss.str (), MakeBoundCallback (&PointToPointHelper::AsciiRxEvent, writer)); + + oss << "/NodeList/" << nd->GetNode ()->GetId () << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/MacRx"; + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultReceiveSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Enqueue"; - Config::Connect (oss.str (), MakeBoundCallback (&PointToPointHelper::AsciiEnqueueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultEnqueueSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Dequeue"; - Config::Connect (oss.str (), MakeBoundCallback (&PointToPointHelper::AsciiDequeueEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDequeueSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::PointToPointNetDevice/TxQueue/Drop"; - Config::Connect (oss.str (), MakeBoundCallback (&PointToPointHelper::AsciiDropEvent, writer)); -} - -void -PointToPointHelper::EnableAscii (std::ostream &os, NetDeviceContainer d) -{ - for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) - { - Ptr dev = *i; - EnableAscii (os, dev->GetNode ()->GetId (), dev->GetIfIndex ()); - } -} - -void -PointToPointHelper::EnableAscii (std::ostream &os, NodeContainer n) -{ - NetDeviceContainer devs; - for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) - { - Ptr node = *i; - for (uint32_t j = 0; j < node->GetNDevices (); ++j) - { - devs.Add (node->GetDevice (j)); - } - } - EnableAscii (os, devs); -} - -void -PointToPointHelper::EnableAsciiAll (std::ostream &os) -{ - EnableAscii (os, NodeContainer::GetGlobal ()); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiTraceHelper::DefaultDropSinkWithContext, stream)); } NetDeviceContainer @@ -194,29 +231,4 @@ PointToPointHelper::Install (std::string aName, std::string bName) return Install (a, b); } -void -PointToPointHelper::AsciiEnqueueEvent (Ptr writer, std::string path, - Ptr packet) -{ - writer->WritePacket (AsciiWriter::ENQUEUE, path, packet); -} - -void -PointToPointHelper::AsciiDequeueEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::DEQUEUE, path, packet); -} - -void -PointToPointHelper::AsciiDropEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::DROP, path, packet); -} - -void -PointToPointHelper::AsciiRxEvent (Ptr writer, std::string path, Ptr packet) -{ - writer->WritePacket (AsciiWriter::RX, path, packet); -} - } // namespace ns3 diff --git a/src/helper/point-to-point-helper.h b/src/helper/point-to-point-helper.h index 2b3774391..e8ae691ea 100644 --- a/src/helper/point-to-point-helper.h +++ b/src/helper/point-to-point-helper.h @@ -20,25 +20,26 @@ #ifndef POINT_TO_POINT_HELPER_H #define POINT_TO_POINT_HELPER_H +#include + #include "ns3/object-factory.h" #include "ns3/net-device-container.h" #include "ns3/node-container.h" #include "ns3/deprecated.h" -#include "pcap-user-helper.h" -#include + +#include "pcap-user-helper-for-device.h" +#include "ascii-trace-user-helper-for-device.h" namespace ns3 { class Queue; class NetDevice; class Node; -class PcapWriter; -class AsciiWriter; /** * \brief Build a set of PointToPointNetDevice objects */ -class PointToPointHelper : public PcapUserHelper +class PointToPointHelper : public PcapUserHelperForDevice, public AsciiTraceUserHelperForDevice { public: /** @@ -95,48 +96,6 @@ public: */ void SetChannelAttribute (std::string name, const AttributeValue &value); - /** - * \param os output stream - * \param nodeid the id of the node to generate ascii output for. - * \param deviceid the id of the device to generate ascii output for. - * - * Enable ascii output on the specified deviceid within the - * specified nodeid if it is of type ns3::PointToPointNetDevice and dump - * that to the specified stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid); - - /** - * \param os output stream - * \param d device container - * - * Enable ascii output on each device which is of the - * ns3::PointToPointNetDevice type and which is located in the input - * device container and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NetDeviceContainer d); - - /** - * \param os output stream - * \param n node container - * - * Enable ascii output on each device which is of the - * ns3::PointToPointNetDevice type and which is located in one - * of the input node and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NodeContainer n); - - /** - * \param os output stream - * - * Enable ascii output on each device which is of the - * ns3::PointToPointNetDevice type and dump that to the specified - * stdc++ output stream. - */ - static void EnableAsciiAll (std::ostream &os); - /** * \param c a set of nodes * @@ -194,11 +153,18 @@ private: */ virtual void EnablePcapInternal (std::string prefix, Ptr nd, bool promiscuous = false); - void EnableAscii (Ptr node, Ptr device); - static void AsciiRxEvent (Ptr writer, std::string path, Ptr packet); - static void AsciiEnqueueEvent (Ptr writer, std::string path, Ptr packet); - static void AsciiDequeueEvent (Ptr writer, std::string path, Ptr packet); - static void AsciiDropEvent (Ptr writer, std::string path, Ptr packet); + /** + * \brief Enable ascii trace output on the indicated net device. + * \internal + * + * NetDevice-specific implementation mechanism for hooking the trace and + * writing to the trace file. + * + * \param stream The output stream object to use when logging ascii traces. + * \param prefix Filename prefix to use for ascii trace files. + * \param nd Net device for which you want to enable tracing. + */ + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd); ObjectFactory m_queueFactory; ObjectFactory m_channelFactory; diff --git a/src/helper/wscript b/src/helper/wscript index 2f2033119..f017e8a00 100644 --- a/src/helper/wscript +++ b/src/helper/wscript @@ -49,8 +49,10 @@ def build(bld): 'csma-star-helper.cc', 'udp-client-server-helper.cc', 'pcap-helper.cc', - 'pcap-user-helper.cc', - 'ascii-trace-user-helper.cc', + 'pcap-user-helper-for-device.cc', + 'pcap-user-helper-for-ipv4.cc', + 'ascii-trace-user-helper-for-device.cc', + 'ascii-trace-user-helper-for-ipv4.cc', 'ascii-trace-helper.cc', ] @@ -104,8 +106,10 @@ def build(bld): 'csma-star-helper.h', 'udp-client-server-helper.h', 'pcap-helper.h', - 'pcap-user-helper.h', - 'ascii-trace-user-helper.h', + 'pcap-user-helper-for-device.h', + 'pcap-user-helper-for-ipv4.h', + 'ascii-trace-user-helper-for-device.h', + 'ascii-trace-user-helper-for-ipv4.h', 'ascii-trace-helper.h', ] diff --git a/src/helper/yans-wifi-helper.cc b/src/helper/yans-wifi-helper.cc index ef4e1683e..904a1e844 100644 --- a/src/helper/yans-wifi-helper.cc +++ b/src/helper/yans-wifi-helper.cc @@ -17,8 +17,9 @@ * * Author: Mathieu Lacage */ + #include "pcap-helper.h" -#include "pcap-user-helper.h" +#include "ascii-trace-helper.h" #include "yans-wifi-helper.h" #include "ns3/error-rate-model.h" #include "ns3/propagation-loss-model.h" @@ -40,21 +41,55 @@ NS_LOG_COMPONENT_DEFINE ("YansWifiHelper"); namespace ns3 { -static void AsciiPhyTxEvent (Ptr writer, std::string path, - Ptr packet, - WifiMode mode, WifiPreamble preamble, - uint8_t txLevel) +static void +AsciiPhyTransmitSinkWithContext ( + Ptr stream, + std::string context, + Ptr p, + WifiMode mode, + WifiPreamble preamble, + uint8_t txLevel) { - writer->WritePacket (AsciiWriter::TX, path, packet); + NS_LOG_FUNCTION (stream << context << p << mode << preamble << txLevel); + *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; } -static void AsciiPhyRxOkEvent (Ptr writer, std::string path, - Ptr packet, double snr, WifiMode mode, - enum WifiPreamble preamble) +static void +AsciiPhyTransmitSinkWithoutContext ( + Ptr stream, + Ptr p, + WifiMode mode, + WifiPreamble preamble, + uint8_t txLevel) { - writer->WritePacket (AsciiWriter::RX, path, packet); + NS_LOG_FUNCTION (stream << p << mode << preamble << txLevel); + *stream->GetStream () << "t " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; } +static void +AsciiPhyReceiveSinkWithContext ( + Ptr stream, + std::string context, + Ptr p, + double snr, + WifiMode mode, + enum WifiPreamble preamble) +{ + NS_LOG_FUNCTION (stream << context << p << snr << mode << preamble); + *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << context << " " << *p << std::endl; +} + +static void +AsciiPhyReceiveSinkWithoutContext ( + Ptr stream, + Ptr p, + double snr, + WifiMode mode, + enum WifiPreamble preamble) +{ + NS_LOG_FUNCTION (stream << p << snr << mode << preamble); + *stream->GetStream () << "r " << Simulator::Now ().GetSeconds () << " " << *p << std::endl; +} YansWifiChannelHelper::YansWifiChannelHelper () {} @@ -372,7 +407,7 @@ YansWifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr nd, bo NS_ABORT_MSG_IF (phy == 0, "YansWifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set"); PcapHelper pcapHelper; - std::string filename = pcapHelper.GetFilename (prefix, device); + std::string filename = pcapHelper.GetFilenameFromDevice (prefix, device); Ptr file = pcapHelper.CreateFile (filename, "w", m_pcapDlt); @@ -381,45 +416,78 @@ YansWifiPhyHelper::EnablePcapInternal (std::string prefix, Ptr nd, bo } void -YansWifiPhyHelper::EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid) +YansWifiPhyHelper::EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd) { - Ptr writer = AsciiWriter::Get (os); + // + // All of the ascii enable functions vector through here including the ones + // that are wandering through all of devices on perhaps all of the nodes in + // the system. We can only deal with devices of type CsmaNetDevice. + // + Ptr device = nd->GetObject (); + if (device == 0) + { + NS_LOG_INFO ("YansWifiHelper::EnableAsciiInternal(): Device " << device << " not of type ns3::WifiNetDevice"); + return; + } + + // + // Our trace sinks are going to use packet printing, so we have to make sure + // that is turned on. + // Packet::EnablePrinting (); + + uint32_t nodeid = nd->GetNode ()->GetId (); + uint32_t deviceid = nd->GetIfIndex (); std::ostringstream oss; + + // + // If we are not provided an OutputStreamObject, we are expected to create + // one using the usual trace filename conventions and write our traces + // without a context since there will be one file per context and therefore + // the context would be redundant. + // + if (stream == 0) + { + // + // Set up an output stream object to deal with private ofstream copy + // constructor and lifetime issues. Let the helper decide the actual + // name of the file given the prefix. + // + AsciiTraceHelper asciiTraceHelper; + std::string filename = asciiTraceHelper.GetFilenameFromDevice (prefix, device); + Ptr theStream = asciiTraceHelper.CreateFileStream (filename, "w"); + + // + // We could go poking through the phy and the state looking for the + // correct trace source, but we can let Config deal with that with + // some search cost. Since this is presumably happening at topology + // creation time, it doesn't seem much of a price to pay. + // + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk"; + Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithoutContext, stream)); + + oss.str (""); + oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx"; + Config::ConnectWithoutContext (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithoutContext, stream)); + + return; + } + + // + // If we are provided an OutputStreamObject, we are expected to use it, and + // to provide a context. We are free to come up with our own context if we + // want, and use the AsciiTraceHelper Hook*WithContext functions, but for + // compatibility and simplicity, we just use Config::Connect and let it deal + // with coming up with a context. + // + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/RxOk"; - Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyRxOkEvent, writer)); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyReceiveSinkWithContext, stream)); + oss.str (""); oss << "/NodeList/" << nodeid << "/DeviceList/" << deviceid << "/$ns3::WifiNetDevice/Phy/State/Tx"; - Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTxEvent, writer)); -} -void -YansWifiPhyHelper::EnableAscii (std::ostream &os, NetDeviceContainer d) -{ - for (NetDeviceContainer::Iterator i = d.Begin (); i != d.End (); ++i) - { - Ptr dev = *i; - EnableAscii (os, dev->GetNode ()->GetId (), dev->GetIfIndex ()); - } -} -void -YansWifiPhyHelper::EnableAscii (std::ostream &os, NodeContainer n) -{ - NetDeviceContainer devs; - for (NodeContainer::Iterator i = n.Begin (); i != n.End (); ++i) - { - Ptr node = *i; - for (uint32_t j = 0; j < node->GetNDevices (); ++j) - { - devs.Add (node->GetDevice (j)); - } - } - EnableAscii (os, devs); -} - -void -YansWifiPhyHelper::EnableAsciiAll (std::ostream &os) -{ - EnableAscii (os, NodeContainer::GetGlobal ()); + Config::Connect (oss.str (), MakeBoundCallback (&AsciiPhyTransmitSinkWithContext, stream)); } } // namespace ns3 diff --git a/src/helper/yans-wifi-helper.h b/src/helper/yans-wifi-helper.h index 79b1ae8ba..7424358c6 100644 --- a/src/helper/yans-wifi-helper.h +++ b/src/helper/yans-wifi-helper.h @@ -21,7 +21,8 @@ #define YANS_WIFI_HELPER_H #include "wifi-helper.h" -#include "pcap-user-helper.h" +#include "pcap-user-helper-for-device.h" +#include "ascii-trace-user-helper-for-device.h" #include "ns3/yans-wifi-channel.h" #include "ns3/deprecated.h" @@ -135,7 +136,7 @@ private: * The Pcap and ascii traces generated by the EnableAscii and EnablePcap methods defined * in this class correspond to PHY-level traces. */ - class YansWifiPhyHelper : public WifiPhyHelper, public PcapUserHelper +class YansWifiPhyHelper : public WifiPhyHelper, public PcapUserHelperForDevice, public AsciiTraceUserHelperForDevice { public: /** @@ -240,48 +241,6 @@ public: */ void SetPcapDataLinkType (uint32_t dlt); - /** - * \param os output stream - * \param nodeid the id of the node to generate ascii output for. - * \param deviceid the id of the device to generate ascii output for. - * - * Enable ascii output on the specified deviceid within the - * specified nodeid if it is of type ns3::WifiNetDevice and dump - * that to the specified stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid); - - /** - * \param os output stream - * \param d device container - * - * Enable ascii output on each device which is of the - * ns3::WifiNetDevice type and which is located in the input - * device container and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NetDeviceContainer d); - - /** - * \param os output stream - * \param n node container - * - * Enable ascii output on each device which is of the - * ns3::WifiNetDevice type and which is located in one - * of the input node and dump that to the specified - * stdc++ output stream. - */ - static void EnableAscii (std::ostream &os, NodeContainer n); - - /** - * \param os output stream - * - * Enable ascii output on each device which is of the - * ns3::WifiNetDevice type and dump that to the specified - * stdc++ output stream. - */ - static void EnableAsciiAll (std::ostream &os); - private: /** * \param node the node on which we wish to create a wifi PHY @@ -304,6 +263,19 @@ private: */ virtual void EnablePcapInternal (std::string prefix, Ptr nd, bool promiscuous); + /** + * \brief Enable ascii trace output on the indicated net device. + * \internal + * + * NetDevice-specific implementation mechanism for hooking the trace and + * writing to the trace file. + * + * \param stream The output stream object to use when logging ascii traces. + * \param prefix Filename prefix to use for ascii trace files. + * \param nd Net device for which you want to enable tracing. + */ + virtual void EnableAsciiInternal (Ptr stream, std::string prefix, Ptr nd); + ObjectFactory m_phy; ObjectFactory m_errorRateModel; Ptr m_channel;