--- a/doc/tutorial/tracing.texi Mon Jan 25 15:28:43 2010 -0800
+++ b/doc/tutorial/tracing.texi Mon Jan 25 16:09:07 2010 -0800
@@ -17,6 +17,8 @@
@menu
* Background::
* Overview::
+* A Real Example::
+* Using Mid-Level Helpers::
@end menu
@c ============================================================================
@@ -1901,4 +1903,30 @@
@sp 1
@center @image{figures/cwnd,,,,png}
+@c ============================================================================
+@c Using Mid-Level Helpers
+@c ============================================================================
+@node Using Mid-Level Helpers
+@section Using Mid-Level Helpers
+In the previous section, we showed how to hook a trace source and get hopefully
+interesting information out of a simulation. Perhaps you will recall that we
+called logging to the standard output using @code{std::cout} a ``Blunt Instrument''
+much earlier in this chapter. We also wrote about how it was a problem having
+to parse the log output in order to isolate interesting information. It may
+have occurred to you that we just spent a lot of time implementing an example
+that exhibits all of the problems we purport to fix with the @code{ns-3} tracing
+system! You would be correct. But, bear with us. We're not done yet.
+
+One of the most important things we want to do is to is to have the ability to
+easily control the amount of output coming out of the simulation; and we also
+want to save those data to a file so we can refer back to it later. We can use
+the mid-level trace helpers provided in @code{ns-3} to do just that and complete
+the picture.
+
+
+
+
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/tutorial/sixth.cc Mon Jan 25 16:09:07 2010 -0800
@@ -0,0 +1,231 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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 <fstream>
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/ascii-trace-helper.h"
+#include "ns3/pcap-helper.h"
+
+using namespace ns3;
+
+NS_LOG_COMPONENT_DEFINE ("SixthScriptExample");
+
+// ===========================================================================
+//
+// node 0 node 1
+// +----------------+ +----------------+
+// | ns-3 TCP | | ns-3 TCP |
+// +----------------+ +----------------+
+// | 10.1.1.1 | | 10.1.1.2 |
+// +----------------+ +----------------+
+// | point-to-point | | point-to-point |
+// +----------------+ +----------------+
+// | |
+// +---------------------+
+// 5 Mbps, 2 ms
+//
+//
+// We want to look at changes in the ns-3 TCP congestion window. We need
+// to crank up a flow and hook the CongestionWindow attribute on the socket
+// of the sender. Normally one would use an on-off application to generate a
+// flow, but this has a couple of problems. First, the socket of the on-off
+// application is not created until Application Start time, so we wouldn't be
+// able to hook the socket (now) at configuration time. Second, even if we
+// could arrange a call after start time, the socket is not public so we
+// couldn't get at it.
+//
+// So, we can cook up a simple version of the on-off application that does what
+// we want. On the plus side we don't need all of the complexity of the on-off
+// application. On the minus side, we don't have a helper, so we have to get
+// a little more involved in the details, but this is trivial.
+//
+// So first, we create a socket and do the trace connect on it; then we pass
+// this socket into the constructor of our simple application which we then
+// install in the source node.
+// ===========================================================================
+//
+class MyApp : public Application
+{
+public:
+
+ MyApp ();
+ virtual ~MyApp();
+
+ void Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate);
+
+private:
+ virtual void StartApplication (void);
+ virtual void StopApplication (void);
+
+ void ScheduleTx (void);
+ void SendPacket (void);
+
+ Ptr<Socket> m_socket;
+ Address m_peer;
+ uint32_t m_packetSize;
+ uint32_t m_nPackets;
+ DataRate m_dataRate;
+ EventId m_sendEvent;
+ bool m_running;
+ uint32_t m_packetsSent;
+};
+
+MyApp::MyApp ()
+ : m_socket (0),
+ m_peer (),
+ m_packetSize (0),
+ m_nPackets (0),
+ m_dataRate (0),
+ m_sendEvent (),
+ m_running (false),
+ m_packetsSent (0)
+{
+}
+
+MyApp::~MyApp()
+{
+ m_socket = 0;
+}
+
+void
+MyApp::Setup (Ptr<Socket> socket, Address address, uint32_t packetSize, uint32_t nPackets, DataRate dataRate)
+{
+ m_socket = socket;
+ m_peer = address;
+ m_packetSize = packetSize;
+ m_nPackets = nPackets;
+ m_dataRate = dataRate;
+}
+
+void
+MyApp::StartApplication (void)
+{
+ m_running = true;
+ m_packetsSent = 0;
+ m_socket->Bind ();
+ m_socket->Connect (m_peer);
+ SendPacket ();
+}
+
+void
+MyApp::StopApplication (void)
+{
+ m_running = false;
+
+ if (m_sendEvent.IsRunning ())
+ {
+ Simulator::Cancel (m_sendEvent);
+ }
+
+ if (m_socket)
+ {
+ m_socket->Close ();
+ }
+}
+
+void
+MyApp::SendPacket (void)
+{
+ Ptr<Packet> packet = Create<Packet> (m_packetSize);
+ m_socket->Send (packet);
+
+ if (++m_packetsSent < m_nPackets)
+ {
+ ScheduleTx ();
+ }
+}
+
+void
+MyApp::ScheduleTx (void)
+{
+ if (m_running)
+ {
+ Time tNext (Seconds (m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ())));
+ m_sendEvent = Simulator::Schedule (tNext, &MyApp::SendPacket, this);
+ }
+}
+
+static void
+CwndChange (Ptr<OutputStreamObject> stream, uint32_t oldCwnd, uint32_t newCwnd)
+{
+ *stream->GetStream () << Simulator::Now ().GetSeconds () << "\t" << oldCwnd << "\t" << newCwnd << std::endl;
+}
+
+static void
+RxDrop (Ptr<PcapFileObject> file, Ptr<const Packet> p)
+{
+ file->Write(Simulator::Now(), p);
+}
+
+int
+main (int argc, char *argv[])
+{
+ NodeContainer nodes;
+ nodes.Create (2);
+
+ PointToPointHelper pointToPoint;
+ pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+ pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
+
+ NetDeviceContainer devices;
+ devices = pointToPoint.Install (nodes);
+
+ Ptr<RateErrorModel> em = CreateObjectWithAttributes<RateErrorModel> (
+ "RanVar", RandomVariableValue (UniformVariable (0., 1.)),
+ "ErrorRate", DoubleValue (0.00001));
+ devices.Get (1)->SetAttribute ("ReceiveErrorModel", PointerValue (em));
+
+ InternetStackHelper stack;
+ stack.Install (nodes);
+
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.252");
+ Ipv4InterfaceContainer interfaces = address.Assign (devices);
+
+ uint16_t sinkPort = 8080;
+ Address sinkAddress (InetSocketAddress(interfaces.GetAddress (1), sinkPort));
+ PacketSinkHelper packetSinkHelper ("ns3::TcpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), sinkPort));
+ ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (1));
+ sinkApps.Start (Seconds (0.));
+ sinkApps.Stop (Seconds (20.));
+
+ Ptr<Socket> ns3TcpSocket = Socket::CreateSocket (nodes.Get (0), TcpSocketFactory::GetTypeId ());
+
+ AsciiTraceHelper asciiTraceHelper;
+ Ptr<OutputStreamObject> stream = asciiTraceHelper.CreateFileStream ("sixth.cwnd");
+ ns3TcpSocket->TraceConnectWithoutContext ("CongestionWindow", MakeBoundCallback (&CwndChange, stream));
+
+ Ptr<MyApp> app = CreateObject<MyApp> ();
+ app->Setup (ns3TcpSocket, sinkAddress, 1040, 1000, DataRate ("1Mbps"));
+ nodes.Get (0)->AddApplication (app);
+ app->SetStartTime (Seconds (1.));
+ app->SetStopTime (Seconds (20.));
+
+ PcapHelper pcapHelper;
+ Ptr<PcapFileObject> file = pcapHelper.CreateFile ("sixth.pcap", "w", PcapHelper::DLT_EN10MB);
+ devices.Get (1)->TraceConnectWithoutContext("PhyRxDrop", MakeBoundCallback (&RxDrop, file));
+
+ Simulator::Stop (Seconds(20));
+ Simulator::Run ();
+ Simulator::Destroy ();
+
+ return 0;
+}
+
--- a/examples/tutorial/wscript Mon Jan 25 15:28:43 2010 -0800
+++ b/examples/tutorial/wscript Mon Jan 25 16:09:07 2010 -0800
@@ -18,3 +18,6 @@
obj = bld.create_ns3_program('fifth', ['core', 'simulator', 'point-to-point', 'internet-stack'])
obj.source = 'fifth.cc'
+
+ obj = bld.create_ns3_program('sixth', ['core', 'simulator', 'point-to-point', 'internet-stack'])
+ obj.source = 'sixth.cc'