A Discrete-Event Network Simulator
API
onoff-application.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2006 Georgia Tech Research Corporation
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License version 2 as
6 // published by the Free Software Foundation;
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // Author: George F. Riley<riley@ece.gatech.edu>
18 //
19 
20 // ns3 - On/Off Data Source Application class
21 // George F. Riley, Georgia Tech, Spring 2007
22 // Adapted from ApplicationOnOff in GTNetS.
23 
24 #include "onoff-application.h"
25 
26 #include "ns3/address.h"
27 #include "ns3/boolean.h"
28 #include "ns3/data-rate.h"
29 #include "ns3/inet-socket-address.h"
30 #include "ns3/inet6-socket-address.h"
31 #include "ns3/log.h"
32 #include "ns3/node.h"
33 #include "ns3/nstime.h"
34 #include "ns3/packet-socket-address.h"
35 #include "ns3/packet.h"
36 #include "ns3/pointer.h"
37 #include "ns3/random-variable-stream.h"
38 #include "ns3/simulator.h"
39 #include "ns3/socket-factory.h"
40 #include "ns3/socket.h"
41 #include "ns3/string.h"
42 #include "ns3/trace-source-accessor.h"
43 #include "ns3/udp-socket-factory.h"
44 #include "ns3/uinteger.h"
45 
46 namespace ns3
47 {
48 
49 NS_LOG_COMPONENT_DEFINE("OnOffApplication");
50 
51 NS_OBJECT_ENSURE_REGISTERED(OnOffApplication);
52 
53 TypeId
55 {
56  static TypeId tid =
57  TypeId("ns3::OnOffApplication")
59  .SetGroupName("Applications")
60  .AddConstructor<OnOffApplication>()
61  .AddAttribute("DataRate",
62  "The data rate in on state.",
63  DataRateValue(DataRate("500kb/s")),
64  MakeDataRateAccessor(&OnOffApplication::m_cbrRate),
65  MakeDataRateChecker())
66  .AddAttribute("PacketSize",
67  "The size of packets sent in on state",
68  UintegerValue(512),
70  MakeUintegerChecker<uint32_t>(1))
71  .AddAttribute("Remote",
72  "The address of the destination",
73  AddressValue(),
74  MakeAddressAccessor(&OnOffApplication::m_peer),
75  MakeAddressChecker())
76  .AddAttribute("Local",
77  "The Address on which to bind the socket. If not set, it is generated "
78  "automatically.",
79  AddressValue(),
80  MakeAddressAccessor(&OnOffApplication::m_local),
81  MakeAddressChecker())
82  .AddAttribute("OnTime",
83  "A RandomVariableStream used to pick the duration of the 'On' state.",
84  StringValue("ns3::ConstantRandomVariable[Constant=1.0]"),
86  MakePointerChecker<RandomVariableStream>())
87  .AddAttribute("OffTime",
88  "A RandomVariableStream used to pick the duration of the 'Off' state.",
89  StringValue("ns3::ConstantRandomVariable[Constant=1.0]"),
91  MakePointerChecker<RandomVariableStream>())
92  .AddAttribute("MaxBytes",
93  "The total number of bytes to send. Once these bytes are sent, "
94  "no packet is sent again, even in on state. The value zero means "
95  "that there is no limit.",
96  UintegerValue(0),
98  MakeUintegerChecker<uint64_t>())
99  .AddAttribute("Protocol",
100  "The type of protocol to use. This should be "
101  "a subclass of ns3::SocketFactory",
104  // This should check for SocketFactory as a parent
106  .AddAttribute("EnableSeqTsSizeHeader",
107  "Enable use of SeqTsSizeHeader for sequence number and timestamp",
108  BooleanValue(false),
111  .AddTraceSource("Tx",
112  "A new packet is created and is sent",
114  "ns3::Packet::TracedCallback")
115  .AddTraceSource("TxWithAddresses",
116  "A new packet is created and is sent",
118  "ns3::Packet::TwoAddressTracedCallback")
119  .AddTraceSource("TxWithSeqTsSize",
120  "A new packet is created with SeqTsSizeHeader",
122  "ns3::PacketSink::SeqTsSizeCallback");
123  return tid;
124 }
125 
127  : m_socket(nullptr),
128  m_connected(false),
129  m_residualBits(0),
130  m_lastStartTime(Seconds(0)),
131  m_totBytes(0),
132  m_unsentPacket(nullptr)
133 {
134  NS_LOG_FUNCTION(this);
135 }
136 
138 {
139  NS_LOG_FUNCTION(this);
140 }
141 
142 void
144 {
145  NS_LOG_FUNCTION(this << maxBytes);
146  m_maxBytes = maxBytes;
147 }
148 
151 {
152  NS_LOG_FUNCTION(this);
153  return m_socket;
154 }
155 
156 int64_t
158 {
159  NS_LOG_FUNCTION(this << stream);
160  m_onTime->SetStream(stream);
161  m_offTime->SetStream(stream + 1);
162  return 2;
163 }
164 
165 void
167 {
168  NS_LOG_FUNCTION(this);
169 
170  CancelEvents();
171  m_socket = nullptr;
172  m_unsentPacket = nullptr;
173  // chain up
175 }
176 
177 // Application Methods
178 void
179 OnOffApplication::StartApplication() // Called at time specified by Start
180 {
181  NS_LOG_FUNCTION(this);
182 
183  // Create the socket if not already
184  if (!m_socket)
185  {
187  int ret = -1;
188 
189  if (!m_local.IsInvalid())
190  {
195  "Incompatible peer and local address IP version");
196  ret = m_socket->Bind(m_local);
197  }
198  else
199  {
201  {
202  ret = m_socket->Bind6();
203  }
206  {
207  ret = m_socket->Bind();
208  }
209  }
210 
211  if (ret == -1)
212  {
213  NS_FATAL_ERROR("Failed to bind socket");
214  }
215 
218 
222  }
224 
225  // Ensure no pending event
226  CancelEvents();
227 
228  // If we are not yet connected, there is nothing to do here,
229  // the ConnectionComplete upcall will start timers at that time.
230  // If we are already connected, CancelEvents did remove the events,
231  // so we have to start them again.
232  if (m_connected)
233  {
235  }
236 }
237 
238 void
239 OnOffApplication::StopApplication() // Called at time specified by Stop
240 {
241  NS_LOG_FUNCTION(this);
242 
243  CancelEvents();
244  if (m_socket)
245  {
246  m_socket->Close();
247  }
248  else
249  {
250  NS_LOG_WARN("OnOffApplication found null socket to close in StopApplication");
251  }
252 }
253 
254 void
256 {
257  NS_LOG_FUNCTION(this);
258 
260  { // Cancel the pending send packet event
261  // Calculate residual bits since last packet sent
264  m_residualBits += bits.GetHigh();
265  }
269  // Canceling events may cause discontinuity in sequence number if the
270  // SeqTsSizeHeader is header, and m_unsentPacket is true
271  if (m_unsentPacket)
272  {
273  NS_LOG_DEBUG("Discarding cached packet upon CancelEvents ()");
274  }
275  m_unsentPacket = nullptr;
276 }
277 
278 // Event handlers
279 void
281 {
282  NS_LOG_FUNCTION(this);
284  ScheduleNextTx(); // Schedule the send packet event
286 }
287 
288 void
290 {
291  NS_LOG_FUNCTION(this);
292  CancelEvents();
293 
295 }
296 
297 // Private helpers
298 void
300 {
301  NS_LOG_FUNCTION(this);
302 
303  if (m_maxBytes == 0 || m_totBytes < m_maxBytes)
304  {
306  "Calculation to compute next send time will overflow");
307  uint32_t bits = m_pktSize * 8 - m_residualBits;
308  NS_LOG_LOGIC("bits = " << bits);
309  Time nextTime(
310  Seconds(bits / static_cast<double>(m_cbrRate.GetBitRate()))); // Time till next packet
311  NS_LOG_LOGIC("nextTime = " << nextTime.As(Time::S));
313  }
314  else
315  { // All done, cancel any pending events
316  StopApplication();
317  }
318 }
319 
320 void
322 { // Schedules the event to start sending data (switch to the "On" state)
323  NS_LOG_FUNCTION(this);
324 
325  Time offInterval = Seconds(m_offTime->GetValue());
326  NS_LOG_LOGIC("start at " << offInterval.As(Time::S));
328 }
329 
330 void
332 { // Schedules the event to stop sending data (switch to "Off" state)
333  NS_LOG_FUNCTION(this);
334 
335  Time onInterval = Seconds(m_onTime->GetValue());
336  NS_LOG_LOGIC("stop at " << onInterval.As(Time::S));
338 }
339 
340 void
342 {
343  NS_LOG_FUNCTION(this);
344 
346 
347  Ptr<Packet> packet;
348  if (m_unsentPacket)
349  {
350  packet = m_unsentPacket;
351  }
352  else if (m_enableSeqTsSizeHeader)
353  {
354  Address from;
355  Address to;
356  m_socket->GetSockName(from);
357  m_socket->GetPeerName(to);
358  SeqTsSizeHeader header;
359  header.SetSeq(m_seq++);
360  header.SetSize(m_pktSize);
362  packet = Create<Packet>(m_pktSize - header.GetSerializedSize());
363  // Trace before adding header, for consistency with PacketSink
364  m_txTraceWithSeqTsSize(packet, from, to, header);
365  packet->AddHeader(header);
366  }
367  else
368  {
369  packet = Create<Packet>(m_pktSize);
370  }
371 
372  int actual = m_socket->Send(packet);
373  if ((unsigned)actual == m_pktSize)
374  {
375  m_txTrace(packet);
377  m_unsentPacket = nullptr;
378  Address localAddress;
379  m_socket->GetSockName(localAddress);
381  {
382  NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " on-off application sent "
383  << packet->GetSize() << " bytes to "
386  << " total Tx " << m_totBytes << " bytes");
388  }
390  {
391  NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " on-off application sent "
392  << packet->GetSize() << " bytes to "
395  << " total Tx " << m_totBytes << " bytes");
397  }
398  }
399  else
400  {
401  NS_LOG_DEBUG("Unable to send packet; actual " << actual << " size " << m_pktSize
402  << "; caching for later attempt");
403  m_unsentPacket = packet;
404  }
405  m_residualBits = 0;
407  ScheduleNextTx();
408 }
409 
410 void
412 {
413  NS_LOG_FUNCTION(this << socket);
414 
416  m_connected = true;
417 }
418 
419 void
421 {
422  NS_LOG_FUNCTION(this << socket);
423  NS_FATAL_ERROR("Can't connect");
424 }
425 
426 } // Namespace ns3
a polymophic address class
Definition: address.h:101
bool IsInvalid() const
Definition: address.cc:71
The base class for all ns3 applications.
Definition: application.h:62
void DoDispose() override
Destructor implementation.
Definition: application.cc:86
Ptr< Node > GetNode() const
Definition: application.cc:108
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
bool IsExpired() const
This method is syntactic sugar for the ns3::Simulator::IsExpired method.
Definition: event-id.cc:69
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint16_t GetPort() const
Get the port.
static bool IsMatchingType(const Address &addr)
If the address match.
Ipv6Address GetIpv6() const
Get the IPv6 address.
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Generate traffic to a single destination according to an OnOff pattern.
static TypeId GetTypeId()
Get the type ID.
uint32_t m_residualBits
Number of generated, but not sent, bits.
void ConnectionSucceeded(Ptr< Socket > socket)
Handle a Connection Succeed event.
EventId m_sendEvent
Event id of pending "send packet" event.
void ScheduleStartEvent()
Schedule the next On period start.
bool m_connected
True if connected.
uint32_t m_pktSize
Size of packets.
Ptr< Socket > GetSocket() const
Return a pointer to associated socket.
Ptr< Socket > m_socket
Associated socket.
TracedCallback< Ptr< const Packet > > m_txTrace
Traced Callback: transmitted packets.
void SetMaxBytes(uint64_t maxBytes)
Set the total number of bytes to send.
Ptr< RandomVariableStream > m_offTime
rng for Off Time
void StartApplication() override
Application specific startup code.
Ptr< Packet > m_unsentPacket
Unsent packet cached for future attempt.
TracedCallback< Ptr< const Packet >, const Address &, const Address & > m_txTraceWithAddresses
Callbacks for tracing the packet Tx events, includes source and destination addresses.
void DoDispose() override
Destructor implementation.
EventId m_startStopEvent
Event id for next start or stop event.
void ScheduleNextTx()
Schedule the next packet transmission.
DataRate m_cbrRateFailSafe
Rate that data is generated (check copy)
void ConnectionFailed(Ptr< Socket > socket)
Handle a Connection Failed event.
void ScheduleStopEvent()
Schedule the next Off period start.
TracedCallback< Ptr< const Packet >, const Address &, const Address &, const SeqTsSizeHeader & > m_txTraceWithSeqTsSize
Callback for tracing the packet Tx events, includes source, destination, the packet sent,...
uint64_t m_maxBytes
Limit total number of bytes sent.
Time m_lastStartTime
Time last packet sent.
uint64_t m_totBytes
Total bytes sent so far.
void StopSending()
Start an Off period.
void StartSending()
Start an On period.
Address m_local
Local address to bind to.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Ptr< RandomVariableStream > m_onTime
rng for On Time
bool m_enableSeqTsSizeHeader
Enable or disable the use of SeqTsSizeHeader.
TypeId m_tid
Type of the socket used.
uint32_t m_seq
Sequence.
DataRate m_cbrRate
Rate that data is generated.
void StopApplication() override
Application specific shutdown code.
Address m_peer
Peer address.
void CancelEvents()
Cancel all pending events.
void SendPacket()
Send a packet.
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
static bool IsMatchingType(const Address &address)
virtual double GetValue()=0
Get the next random value drawn from the distribution.
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
void SetSeq(uint32_t seq)
Header with a sequence, a timestamp, and a "size" attribute.
uint32_t GetSerializedSize() const override
void SetSize(uint64_t size)
Set the size information that the header will carry.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:285
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
virtual int ShutdownRecv()=0
virtual int Bind6()=0
Allocate a local IPv6 endpoint for this socket.
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int GetSockName(Address &address) const =0
Get socket address.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetConnectCallback(Callback< void, Ptr< Socket >> connectionSucceeded, Callback< void, Ptr< Socket >> connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:87
Hold variables of type string.
Definition: string.h:56
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
@ S
second
Definition: nstime.h:116
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
static TypeId GetTypeId()
Get the type ID.
Hold an unsigned integer type.
Definition: uinteger.h:45
High precision numerical type, implementing Q64.64 fixed precision.
int64_t GetHigh() const
Get the integer portion.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition: abort.h:108
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
void(* DataRate)(DataRate oldValue, DataRate newValue)
TracedValue callback signature for DataRate.
Definition: data-rate.h:327
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Definition: pointer.h:227
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition: type-id.cc:1250
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition: type-id.h:598
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46