A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
onoff-application.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 //
3 // Copyright (c) 2006 Georgia Tech Research Corporation
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License version 2 as
7 // published by the Free Software Foundation;
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 //
18 // Author: George F. Riley<riley@ece.gatech.edu>
19 //
20 
21 // ns3 - On/Off Data Source Application class
22 // George F. Riley, Georgia Tech, Spring 2007
23 // Adapted from ApplicationOnOff in GTNetS.
24 
25 #include "ns3/log.h"
26 #include "ns3/address.h"
27 #include "ns3/inet-socket-address.h"
28 #include "ns3/inet6-socket-address.h"
29 #include "ns3/node.h"
30 #include "ns3/nstime.h"
31 #include "ns3/data-rate.h"
32 #include "ns3/random-variable-stream.h"
33 #include "ns3/socket.h"
34 #include "ns3/simulator.h"
35 #include "ns3/socket-factory.h"
36 #include "ns3/packet.h"
37 #include "ns3/uinteger.h"
38 #include "ns3/trace-source-accessor.h"
39 #include "onoff-application.h"
40 #include "ns3/udp-socket-factory.h"
41 #include "ns3/string.h"
42 #include "ns3/pointer.h"
43 
44 NS_LOG_COMPONENT_DEFINE ("OnOffApplication");
45 
46 using namespace std;
47 
48 namespace ns3 {
49 
50 NS_OBJECT_ENSURE_REGISTERED (OnOffApplication);
51 
52 TypeId
53 OnOffApplication::GetTypeId (void)
54 {
55  static TypeId tid = TypeId ("ns3::OnOffApplication")
57  .AddConstructor<OnOffApplication> ()
58  .AddAttribute ("DataRate", "The data rate in on state.",
59  DataRateValue (DataRate ("500kb/s")),
60  MakeDataRateAccessor (&OnOffApplication::m_cbrRate),
61  MakeDataRateChecker ())
62  .AddAttribute ("PacketSize", "The size of packets sent in on state",
63  UintegerValue (512),
64  MakeUintegerAccessor (&OnOffApplication::m_pktSize),
65  MakeUintegerChecker<uint32_t> (1))
66  .AddAttribute ("Remote", "The address of the destination",
67  AddressValue (),
68  MakeAddressAccessor (&OnOffApplication::m_peer),
69  MakeAddressChecker ())
70  .AddAttribute ("OnTime", "A RandomVariableStream used to pick the duration of the 'On' state.",
71  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
72  MakePointerAccessor (&OnOffApplication::m_onTime),
73  MakePointerChecker <RandomVariableStream>())
74  .AddAttribute ("OffTime", "A RandomVariableStream used to pick the duration of the 'Off' state.",
75  StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"),
76  MakePointerAccessor (&OnOffApplication::m_offTime),
77  MakePointerChecker <RandomVariableStream>())
78  .AddAttribute ("MaxBytes",
79  "The total number of bytes to send. Once these bytes are sent, "
80  "no packet is sent again, even in on state. The value zero means "
81  "that there is no limit.",
82  UintegerValue (0),
83  MakeUintegerAccessor (&OnOffApplication::m_maxBytes),
84  MakeUintegerChecker<uint32_t> ())
85  .AddAttribute ("Protocol", "The type of protocol to use.",
86  TypeIdValue (UdpSocketFactory::GetTypeId ()),
87  MakeTypeIdAccessor (&OnOffApplication::m_tid),
88  MakeTypeIdChecker ())
89  .AddTraceSource ("Tx", "A new packet is created and is sent",
90  MakeTraceSourceAccessor (&OnOffApplication::m_txTrace))
91  ;
92  return tid;
93 }
94 
95 
96 OnOffApplication::OnOffApplication ()
97 {
99  m_socket = 0;
100  m_connected = false;
101  m_residualBits = 0;
102  m_lastStartTime = Seconds (0);
103  m_totBytes = 0;
104 }
105 
106 OnOffApplication::~OnOffApplication()
107 {
109 }
110 
111 void
112 OnOffApplication::SetMaxBytes (uint32_t maxBytes)
113 {
114  NS_LOG_FUNCTION (this << maxBytes);
115  m_maxBytes = maxBytes;
116 }
117 
119 OnOffApplication::GetSocket (void) const
120 {
121  NS_LOG_FUNCTION (this);
122  return m_socket;
123 }
124 
125 int64_t
126 OnOffApplication::AssignStreams (int64_t stream)
127 {
128  NS_LOG_FUNCTION (this << stream);
129  m_onTime->SetStream (stream);
130  m_offTime->SetStream (stream + 1);
131  return 2;
132 }
133 
134 void
135 OnOffApplication::DoDispose (void)
136 {
138 
139  m_socket = 0;
140  // chain up
141  Application::DoDispose ();
142 }
143 
144 // Application Methods
145 void OnOffApplication::StartApplication () // Called at time specified by Start
146 {
148 
149  // Create the socket if not already
150  if (!m_socket)
151  {
152  m_socket = Socket::CreateSocket (GetNode (), m_tid);
153  m_socket->Bind ();
154  m_socket->Connect (m_peer);
155  m_socket->SetAllowBroadcast (true);
156  m_socket->ShutdownRecv ();
157  }
158  // Insure no pending event
159  CancelEvents ();
160  // If we are not yet connected, there is nothing to do here
161  // The ConnectionComplete upcall will start timers at that time
162  //if (!m_connected) return;
163  ScheduleStartEvent ();
164 }
165 
166 void OnOffApplication::StopApplication () // Called at time specified by Stop
167 {
169 
170  CancelEvents ();
171  if(m_socket != 0)
172  {
173  m_socket->Close ();
174  }
175  else
176  {
177  NS_LOG_WARN ("OnOffApplication found null socket to close in StopApplication");
178  }
179 }
180 
181 void OnOffApplication::CancelEvents ()
182 {
184 
185  if (m_sendEvent.IsRunning ())
186  { // Cancel the pending send packet event
187  // Calculate residual bits since last packet sent
188  Time delta (Simulator::Now () - m_lastStartTime);
189  int64x64_t bits = delta.To (Time::S) * m_cbrRate.GetBitRate ();
190  m_residualBits += bits.GetHigh ();
191  }
192  Simulator::Cancel (m_sendEvent);
193  Simulator::Cancel (m_startStopEvent);
194 }
195 
196 // Event handlers
197 void OnOffApplication::StartSending ()
198 {
200  m_lastStartTime = Simulator::Now ();
201  ScheduleNextTx (); // Schedule the send packet event
202  ScheduleStopEvent ();
203 }
204 
205 void OnOffApplication::StopSending ()
206 {
208  CancelEvents ();
209 
210  ScheduleStartEvent ();
211 }
212 
213 // Private helpers
214 void OnOffApplication::ScheduleNextTx ()
215 {
217 
218  if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
219  {
220  uint32_t bits = m_pktSize * 8 - m_residualBits;
221  NS_LOG_LOGIC ("bits = " << bits);
222  Time nextTime (Seconds (bits /
223  static_cast<double>(m_cbrRate.GetBitRate ()))); // Time till next packet
224  NS_LOG_LOGIC ("nextTime = " << nextTime);
225  m_sendEvent = Simulator::Schedule (nextTime,
227  }
228  else
229  { // All done, cancel any pending events
230  StopApplication ();
231  }
232 }
233 
234 void OnOffApplication::ScheduleStartEvent ()
235 { // Schedules the event to start sending data (switch to the "On" state)
237 
238  Time offInterval = Seconds (m_offTime->GetValue ());
239  NS_LOG_LOGIC ("start at " << offInterval);
240  m_startStopEvent = Simulator::Schedule (offInterval, &OnOffApplication::StartSending, this);
241 }
242 
243 void OnOffApplication::ScheduleStopEvent ()
244 { // Schedules the event to stop sending data (switch to "Off" state)
246 
247  Time onInterval = Seconds (m_onTime->GetValue ());
248  NS_LOG_LOGIC ("stop at " << onInterval);
249  m_startStopEvent = Simulator::Schedule (onInterval, &OnOffApplication::StopSending, this);
250 }
251 
252 
254 {
256 
257  NS_ASSERT (m_sendEvent.IsExpired ());
258  Ptr<Packet> packet = Create<Packet> (m_pktSize);
259  m_txTrace (packet);
260  m_socket->Send (packet);
261  m_totBytes += m_pktSize;
262  if (InetSocketAddress::IsMatchingType (m_peer))
263  {
264  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
265  << "s on-off application sent "
266  << packet->GetSize () << " bytes to "
267  << InetSocketAddress::ConvertFrom(m_peer).GetIpv4 ()
268  << " port " << InetSocketAddress::ConvertFrom (m_peer).GetPort ()
269  << " total Tx " << m_totBytes << " bytes");
270  }
271  else if (Inet6SocketAddress::IsMatchingType (m_peer))
272  {
273  NS_LOG_INFO ("At time " << Simulator::Now ().GetSeconds ()
274  << "s on-off application sent "
275  << packet->GetSize () << " bytes to "
276  << Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6 ()
277  << " port " << Inet6SocketAddress::ConvertFrom (m_peer).GetPort ()
278  << " total Tx " << m_totBytes << " bytes");
279  }
280  m_lastStartTime = Simulator::Now ();
281  m_residualBits = 0;
282  ScheduleNextTx ();
283 }
284 
285 void OnOffApplication::ConnectionSucceeded (Ptr<Socket>)
286 {
288 
289  m_connected = true;
290  ScheduleStartEvent ();
291 }
292 
293 void OnOffApplication::ConnectionFailed (Ptr<Socket>)
294 {
296  cout << "OnOffApplication, Connection Failed" << endl;
297 }
298 
299 } // Namespace ns3