A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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",
60 .AddAttribute("Local",
61 "The Address on which to bind the socket. If not set, it is generated "
62 "automatically.",
66 .AddAttribute("Tos",
67 "The Type of Service used to send IPv4 packets. "
68 "All 8 bits of the TOS byte are set (including ECN bits).",
71 MakeUintegerChecker<uint8_t>())
72 .AddAttribute("MaxBytes",
73 "The total number of bytes to send. "
74 "Once these bytes are sent, "
75 "no data is sent again. The value zero means "
76 "that there is no limit.",
79 MakeUintegerChecker<uint64_t>())
80 .AddAttribute("Protocol",
81 "The type of protocol to use.",
85 .AddAttribute("EnableSeqTsSizeHeader",
86 "Add SeqTsSizeHeader to each packet",
87 BooleanValue(false),
90 .AddTraceSource("Tx",
91 "A new packet is sent",
93 "ns3::Packet::TracedCallback")
94 .AddTraceSource("TxWithSeqTsSize",
95 "A new packet is created with SeqTsSizeHeader",
97 "ns3::PacketSink::SeqTsSizeCallback");
98 return tid;
99}
100
102 : m_socket(nullptr),
103 m_connected(false),
104 m_totBytes(0),
105 m_unsentPacket(nullptr)
106{
107 NS_LOG_FUNCTION(this);
108}
109
111{
112 NS_LOG_FUNCTION(this);
113}
114
115void
117{
118 NS_LOG_FUNCTION(this << maxBytes);
119 m_maxBytes = maxBytes;
120}
121
124{
125 NS_LOG_FUNCTION(this);
126 return m_socket;
127}
128
129void
131{
132 NS_LOG_FUNCTION(this);
133
134 m_socket = nullptr;
135 m_unsentPacket = nullptr;
136 // chain up
138}
139
140// Application Methods
141void
142BulkSendApplication::StartApplication() // Called at time specified by Start
143{
144 NS_LOG_FUNCTION(this);
145 Address from;
146
147 // Create the socket if not already
148 if (!m_socket)
149 {
151 int ret = -1;
152
153 // Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
156 {
157 NS_FATAL_ERROR("Using BulkSend with an incompatible socket type. "
158 "BulkSend requires SOCK_STREAM or SOCK_SEQPACKET. "
159 "In other words, use TCP instead of UDP.");
160 }
161
162 NS_ABORT_MSG_IF(m_peer.IsInvalid(), "'Remote' attribute not properly set");
163
164 if (!m_local.IsInvalid())
165 {
170 "Incompatible peer and local address IP version");
171 ret = m_socket->Bind(m_local);
172 }
173 else
174 {
176 {
177 ret = m_socket->Bind6();
178 }
180 {
181 ret = m_socket->Bind();
182 }
183 }
184
185 if (ret == -1)
186 {
187 NS_FATAL_ERROR("Failed to bind socket");
188 }
189
191 {
192 m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets.
193 }
199 }
200 if (m_connected)
201 {
202 m_socket->GetSockName(from);
203 SendData(from, m_peer);
204 }
205}
206
207void
208BulkSendApplication::StopApplication() // Called at time specified by Stop
209{
210 NS_LOG_FUNCTION(this);
211
212 if (m_socket)
213 {
214 m_socket->Close();
215 m_connected = false;
216 }
217 else
218 {
219 NS_LOG_WARN("BulkSendApplication found null socket to close in StopApplication");
220 }
221}
222
223// Private helpers
224
225void
227{
228 NS_LOG_FUNCTION(this);
229
230 while (m_maxBytes == 0 || m_totBytes < m_maxBytes)
231 { // Time to send more
232
233 // uint64_t to allow the comparison later.
234 // the result is in a uint32_t range anyway, because
235 // m_sendSize is uint32_t.
236 uint64_t toSend = m_sendSize;
237 // Make sure we don't send too many
238 if (m_maxBytes > 0)
239 {
240 toSend = std::min(toSend, m_maxBytes - m_totBytes);
241 }
242
243 NS_LOG_LOGIC("sending packet at " << Simulator::Now());
244
245 Ptr<Packet> packet;
246 if (m_unsentPacket)
247 {
248 packet = m_unsentPacket;
249 toSend = packet->GetSize();
250 }
252 {
253 SeqTsSizeHeader header;
254 header.SetSeq(m_seq++);
255 header.SetSize(toSend);
256 NS_ABORT_IF(toSend < header.GetSerializedSize());
257 packet = Create<Packet>(toSend - header.GetSerializedSize());
258 // Trace before adding header, for consistency with PacketSink
259 m_txTraceWithSeqTsSize(packet, from, to, header);
260 packet->AddHeader(header);
261 }
262 else
263 {
264 packet = Create<Packet>(toSend);
265 }
266
267 int actual = m_socket->Send(packet);
268 if ((unsigned)actual == toSend)
269 {
270 m_totBytes += actual;
271 m_txTrace(packet);
272 m_unsentPacket = nullptr;
273 }
274 else if (actual == -1)
275 {
276 // We exit this loop when actual < toSend as the send side
277 // buffer is full. The "DataSent" callback will pop when
278 // some buffer space has freed up.
279 NS_LOG_DEBUG("Unable to send packet; caching for later attempt");
280 m_unsentPacket = packet;
281 break;
282 }
283 else if (actual > 0 && (unsigned)actual < toSend)
284 {
285 // A Linux socket (non-blocking, such as in DCE) may return
286 // a quantity less than the packet size. Split the packet
287 // into two, trace the sent packet, save the unsent packet
288 NS_LOG_DEBUG("Packet size: " << packet->GetSize() << "; sent: " << actual
289 << "; fragment saved: " << toSend - (unsigned)actual);
290 Ptr<Packet> sent = packet->CreateFragment(0, actual);
291 Ptr<Packet> unsent = packet->CreateFragment(actual, (toSend - (unsigned)actual));
292 m_totBytes += actual;
293 m_txTrace(sent);
294 m_unsentPacket = unsent;
295 break;
296 }
297 else
298 {
299 NS_FATAL_ERROR("Unexpected return value from m_socket->Send ()");
300 }
301 }
302 // Check if time to close (all sent)
304 {
305 m_socket->Close();
306 m_connected = false;
307 }
308}
309
310void
312{
313 NS_LOG_FUNCTION(this << socket);
314 NS_LOG_LOGIC("BulkSendApplication Connection succeeded");
315 m_connected = true;
316 Address from;
317 Address to;
318 socket->GetSockName(from);
319 socket->GetPeerName(to);
320 SendData(from, to);
321}
322
323void
325{
326 NS_LOG_FUNCTION(this << socket);
327 NS_LOG_LOGIC("BulkSendApplication, Connection Failed");
328}
329
330void
332{
333 NS_LOG_FUNCTION(this);
334
335 if (m_connected)
336 { // Only send new data if the connection has completed
337 Address from;
338 Address to;
339 socket->GetSockName(from);
340 socket->GetPeerName(to);
341 SendData(from, to);
342 }
343}
344
345} // Namespace ns3
a polymophic address class
Definition: address.h:101
bool IsInvalid() const
Definition: address.cc:71
AttributeValue implementation for Address.
Definition: address.h:286
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
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.
uint8_t m_tos
The packets Type of Service.
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)
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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
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
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition: socket.cc:434
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
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.
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:932
AttributeValue implementation for TypeId.
Definition: type-id.h:598
Hold an unsigned integer type.
Definition: uinteger.h:45
Ptr< const AttributeChecker > MakeAddressChecker()
Definition: address.cc:180
Ptr< const AttributeAccessor > MakeAddressAccessor(T1 a1)
Definition: address.h:286
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition: boolean.h:81
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition: boolean.cc:124
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition: type-id.cc:1251
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition: type-id.h:598
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: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.
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:706