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
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
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("BulkSendApplication");
39
40NS_OBJECT_ENSURE_REGISTERED(BulkSendApplication);
41
42TypeId
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",
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.",
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.",
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
109void
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
123void
125{
126 NS_LOG_FUNCTION(this);
127
128 m_socket = nullptr;
129 m_unsentPacket = nullptr;
130 // chain up
132}
133
134// Application Methods
135void
136BulkSendApplication::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
195void
196BulkSendApplication::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
213void
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 }
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
298void
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
311void
313{
314 NS_LOG_FUNCTION(this << socket);
315 NS_LOG_LOGIC("BulkSendApplication, Connection Failed");
316}
317
318void
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:42
a polymophic address class
Definition: address.h:100
bool IsInvalid() const
Definition: address.cc:71
AttributeValue implementation for Address.
The base class for all ns3 applications.
Definition: application.h:61
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
Ptr< Node > GetNode() const
Definition: application.cc:107
AttributeValue implementation for Boolean.
Definition: boolean.h:37
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:863
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:199
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
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:85
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:119
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual int GetSockName(Address &address) const =0
Get socket address.
virtual enum Socket::SocketType GetSocketType() const =0
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.
static TypeId GetTypeId()
Get the type ID.
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
AttributeValue implementation for TypeId.
Definition: type-id.h:600
Hold an unsigned integer type.
Definition: uinteger.h:45
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:86
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition: type-id.cc:1254
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition: type-id.h:600
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:160
#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.
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:691