A Discrete-Event Network Simulator
API
bulk-send-application.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 Georgia Institute of Technology
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 #include "bulk-send-application.h"
21 
22 #include "ns3/address.h"
23 #include "ns3/boolean.h"
24 #include "ns3/log.h"
25 #include "ns3/node.h"
26 #include "ns3/nstime.h"
27 #include "ns3/packet.h"
28 #include "ns3/simulator.h"
29 #include "ns3/socket-factory.h"
30 #include "ns3/socket.h"
31 #include "ns3/tcp-socket-factory.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "ns3/uinteger.h"
34 
35 namespace ns3
36 {
37 
38 NS_LOG_COMPONENT_DEFINE("BulkSendApplication");
39 
40 NS_OBJECT_ENSURE_REGISTERED(BulkSendApplication);
41 
42 TypeId
44 {
45  static TypeId tid =
46  TypeId("ns3::BulkSendApplication")
48  .SetGroupName("Applications")
49  .AddConstructor<BulkSendApplication>()
50  .AddAttribute("SendSize",
51  "The amount of data to send each time.",
52  UintegerValue(512),
54  MakeUintegerChecker<uint32_t>(1))
55  .AddAttribute("Remote",
56  "The address of the destination",
57  AddressValue(),
58  MakeAddressAccessor(&BulkSendApplication::m_peer),
59  MakeAddressChecker())
60  .AddAttribute("Local",
61  "The Address on which to bind the socket. If not set, it is generated "
62  "automatically.",
63  AddressValue(),
64  MakeAddressAccessor(&BulkSendApplication::m_local),
65  MakeAddressChecker())
66  .AddAttribute("MaxBytes",
67  "The total number of bytes to send. "
68  "Once these bytes are sent, "
69  "no data is sent again. The value zero means "
70  "that there is no limit.",
71  UintegerValue(0),
73  MakeUintegerChecker<uint64_t>())
74  .AddAttribute("Protocol",
75  "The type of protocol to use.",
79  .AddAttribute("EnableSeqTsSizeHeader",
80  "Add SeqTsSizeHeader to each packet",
81  BooleanValue(false),
84  .AddTraceSource("Tx",
85  "A new packet is sent",
87  "ns3::Packet::TracedCallback")
88  .AddTraceSource("TxWithSeqTsSize",
89  "A new packet is created with SeqTsSizeHeader",
91  "ns3::PacketSink::SeqTsSizeCallback");
92  return tid;
93 }
94 
96  : m_socket(nullptr),
97  m_connected(false),
98  m_totBytes(0),
99  m_unsentPacket(nullptr)
100 {
101  NS_LOG_FUNCTION(this);
102 }
103 
105 {
106  NS_LOG_FUNCTION(this);
107 }
108 
109 void
111 {
112  NS_LOG_FUNCTION(this << maxBytes);
113  m_maxBytes = maxBytes;
114 }
115 
118 {
119  NS_LOG_FUNCTION(this);
120  return m_socket;
121 }
122 
123 void
125 {
126  NS_LOG_FUNCTION(this);
127 
128  m_socket = nullptr;
129  m_unsentPacket = nullptr;
130  // chain up
132 }
133 
134 // Application Methods
135 void
136 BulkSendApplication::StartApplication() // Called at time specified by Start
137 {
138  NS_LOG_FUNCTION(this);
139  Address from;
140 
141  // Create the socket if not already
142  if (!m_socket)
143  {
145  int ret = -1;
146 
147  // Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
150  {
151  NS_FATAL_ERROR("Using BulkSend with an incompatible socket type. "
152  "BulkSend requires SOCK_STREAM or SOCK_SEQPACKET. "
153  "In other words, use TCP instead of UDP.");
154  }
155 
156  if (!m_local.IsInvalid())
157  {
162  "Incompatible peer and local address IP version");
163  ret = m_socket->Bind(m_local);
164  }
165  else
166  {
168  {
169  ret = m_socket->Bind6();
170  }
172  {
173  ret = m_socket->Bind();
174  }
175  }
176 
177  if (ret == -1)
178  {
179  NS_FATAL_ERROR("Failed to bind socket");
180  }
181 
187  }
188  if (m_connected)
189  {
190  m_socket->GetSockName(from);
191  SendData(from, m_peer);
192  }
193 }
194 
195 void
196 BulkSendApplication::StopApplication() // Called at time specified by Stop
197 {
198  NS_LOG_FUNCTION(this);
199 
200  if (m_socket)
201  {
202  m_socket->Close();
203  m_connected = false;
204  }
205  else
206  {
207  NS_LOG_WARN("BulkSendApplication found null socket to close in StopApplication");
208  }
209 }
210 
211 // Private helpers
212 
213 void
215 {
216  NS_LOG_FUNCTION(this);
217 
218  while (m_maxBytes == 0 || m_totBytes < m_maxBytes)
219  { // Time to send more
220 
221  // uint64_t to allow the comparison later.
222  // the result is in a uint32_t range anyway, because
223  // m_sendSize is uint32_t.
224  uint64_t toSend = m_sendSize;
225  // Make sure we don't send too many
226  if (m_maxBytes > 0)
227  {
228  toSend = std::min(toSend, m_maxBytes - m_totBytes);
229  }
230 
231  NS_LOG_LOGIC("sending packet at " << Simulator::Now());
232 
233  Ptr<Packet> packet;
234  if (m_unsentPacket)
235  {
236  packet = m_unsentPacket;
237  toSend = packet->GetSize();
238  }
239  else if (m_enableSeqTsSizeHeader)
240  {
241  SeqTsSizeHeader header;
242  header.SetSeq(m_seq++);
243  header.SetSize(toSend);
244  NS_ABORT_IF(toSend < header.GetSerializedSize());
245  packet = Create<Packet>(toSend - header.GetSerializedSize());
246  // Trace before adding header, for consistency with PacketSink
247  m_txTraceWithSeqTsSize(packet, from, to, header);
248  packet->AddHeader(header);
249  }
250  else
251  {
252  packet = Create<Packet>(toSend);
253  }
254 
255  int actual = m_socket->Send(packet);
256  if ((unsigned)actual == toSend)
257  {
258  m_totBytes += actual;
259  m_txTrace(packet);
260  m_unsentPacket = nullptr;
261  }
262  else if (actual == -1)
263  {
264  // We exit this loop when actual < toSend as the send side
265  // buffer is full. The "DataSent" callback will pop when
266  // some buffer space has freed up.
267  NS_LOG_DEBUG("Unable to send packet; caching for later attempt");
268  m_unsentPacket = packet;
269  break;
270  }
271  else if (actual > 0 && (unsigned)actual < toSend)
272  {
273  // A Linux socket (non-blocking, such as in DCE) may return
274  // a quantity less than the packet size. Split the packet
275  // into two, trace the sent packet, save the unsent packet
276  NS_LOG_DEBUG("Packet size: " << packet->GetSize() << "; sent: " << actual
277  << "; fragment saved: " << toSend - (unsigned)actual);
278  Ptr<Packet> sent = packet->CreateFragment(0, actual);
279  Ptr<Packet> unsent = packet->CreateFragment(actual, (toSend - (unsigned)actual));
280  m_totBytes += actual;
281  m_txTrace(sent);
282  m_unsentPacket = unsent;
283  break;
284  }
285  else
286  {
287  NS_FATAL_ERROR("Unexpected return value from m_socket->Send ()");
288  }
289  }
290  // Check if time to close (all sent)
292  {
293  m_socket->Close();
294  m_connected = false;
295  }
296 }
297 
298 void
300 {
301  NS_LOG_FUNCTION(this << socket);
302  NS_LOG_LOGIC("BulkSendApplication Connection succeeded");
303  m_connected = true;
304  Address from;
305  Address to;
306  socket->GetSockName(from);
307  socket->GetPeerName(to);
308  SendData(from, to);
309 }
310 
311 void
313 {
314  NS_LOG_FUNCTION(this << socket);
315  NS_LOG_LOGIC("BulkSendApplication, Connection Failed");
316 }
317 
318 void
320 {
321  NS_LOG_FUNCTION(this);
322 
323  if (m_connected)
324  { // Only send new data if the connection has completed
325  Address from;
326  Address to;
327  socket->GetSockName(from);
328  socket->GetPeerName(to);
329  SendData(from, to);
330  }
331 }
332 
333 } // Namespace ns3
#define min(a, b)
Definition: 80211b.c:41
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
Send as much traffic as possible, trying to fill the bandwidth.
bool m_enableSeqTsSizeHeader
Enable or disable the SeqTsSizeHeader.
void SendData(const Address &from, const Address &to)
Send data until the L4 transmission buffer is full.
Ptr< Packet > m_unsentPacket
Variable to cache unsent packet.
void DoDispose() override
Destructor implementation.
void ConnectionSucceeded(Ptr< Socket > socket)
Connection Succeeded (called by Socket through a callback)
static TypeId GetTypeId()
Get the type ID.
bool m_connected
True if connected.
uint32_t m_sendSize
Size of data to send each time.
TracedCallback< Ptr< const Packet > > m_txTrace
Traced Callback: sent packets.
Ptr< Socket > GetSocket() const
Get the socket this application is attached to.
void ConnectionFailed(Ptr< Socket > socket)
Connection Failed (called by Socket through a callback)
uint64_t m_maxBytes
Limit total number of bytes sent.
TypeId m_tid
The type of protocol to use.
void StartApplication() override
Application specific startup code.
uint64_t m_totBytes
Total bytes sent so far.
Ptr< Socket > m_socket
Associated socket.
Address m_local
Local address to bind to.
void DataSend(Ptr< Socket > socket, uint32_t unused)
Send more data as soon as some has been transmitted.
void StopApplication() override
Application specific shutdown code.
void SetMaxBytes(uint64_t maxBytes)
Set the upper bound for the total number of bytes to send.
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,...
static bool IsMatchingType(const Address &addr)
If the address match.
static bool IsMatchingType(const Address &address)
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
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
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 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 Socket::SocketType GetSocketType() const =0
virtual int ShutdownRecv()=0
virtual int Bind6()=0
Allocate a local IPv6 endpoint for this socket.
@ NS3_SOCK_STREAM
Definition: socket.h:108
@ NS3_SOCK_SEQPACKET
Definition: socket.h:109
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition: socket.cc:121
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
static TypeId GetTypeId()
Get the type ID.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Hold an unsigned integer type.
Definition: uinteger.h:45
#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_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
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 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