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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: George F. Riley <riley@ece.gatech.edu>
7 */
8
10
11#include "ns3/address.h"
12#include "ns3/boolean.h"
13#include "ns3/log.h"
14#include "ns3/node.h"
15#include "ns3/nstime.h"
16#include "ns3/packet.h"
17#include "ns3/simulator.h"
18#include "ns3/socket-factory.h"
19#include "ns3/socket.h"
20#include "ns3/tcp-socket-base.h"
21#include "ns3/tcp-socket-factory.h"
22#include "ns3/trace-source-accessor.h"
23#include "ns3/uinteger.h"
24
25namespace ns3
26{
27
28NS_LOG_COMPONENT_DEFINE("BulkSendApplication");
29
30NS_OBJECT_ENSURE_REGISTERED(BulkSendApplication);
31
32TypeId
34{
35 static TypeId tid =
36 TypeId("ns3::BulkSendApplication")
38 .SetGroupName("Applications")
39 .AddConstructor<BulkSendApplication>()
40 .AddAttribute("SendSize",
41 "The amount of data to send each time.",
42 UintegerValue(512),
45 .AddAttribute("Remote",
46 "The address of the destination",
50 .AddAttribute("Local",
51 "The Address on which to bind the socket. If not set, it is generated "
52 "automatically.",
56 .AddAttribute("Tos",
57 "The Type of Service used to send IPv4 packets. "
58 "All 8 bits of the TOS byte are set (including ECN bits).",
62 .AddAttribute("MaxBytes",
63 "The total number of bytes to send. "
64 "Once these bytes are sent, "
65 "no data is sent again. The value zero means "
66 "that there is no limit.",
70 .AddAttribute("Protocol",
71 "The type of protocol to use.",
75 .AddAttribute("EnableSeqTsSizeHeader",
76 "Add SeqTsSizeHeader to each packet",
77 BooleanValue(false),
80 .AddTraceSource("Tx",
81 "A new packet is sent",
83 "ns3::Packet::TracedCallback")
84 .AddTraceSource("TxWithSeqTsSize",
85 "A new packet is created with SeqTsSizeHeader",
87 "ns3::PacketSink::SeqTsSizeCallback")
88 .AddTraceSource("TcpRetransmission",
89 "The TCP socket retransmitted a packet",
91 "ns3::TcpSocketBase::RetransmissionCallback");
92
93 return tid;
94}
95
97 : m_socket(nullptr),
98 m_connected(false),
99 m_totBytes(0),
100 m_unsentPacket(nullptr)
101{
102 NS_LOG_FUNCTION(this);
103}
104
109
110void
112{
113 NS_LOG_FUNCTION(this << maxBytes);
114 m_maxBytes = maxBytes;
115}
116
119{
120 NS_LOG_FUNCTION(this);
121 return m_socket;
122}
123
124void
126{
127 NS_LOG_FUNCTION(this);
128
129 m_socket = nullptr;
130 m_unsentPacket = nullptr;
131 // chain up
133}
134
135// Application Methods
136void
137BulkSendApplication::StartApplication() // Called at time specified by Start
138{
139 NS_LOG_FUNCTION(this);
140 Address from;
141
142 // Create the socket if not already
143 if (!m_socket)
144 {
146 int ret = -1;
147
148 // Fatal error if socket type is not NS3_SOCK_STREAM or NS3_SOCK_SEQPACKET
151 {
152 NS_FATAL_ERROR("Using BulkSend with an incompatible socket type. "
153 "BulkSend requires SOCK_STREAM or SOCK_SEQPACKET. "
154 "In other words, use TCP instead of UDP.");
155 }
156
157 NS_ABORT_MSG_IF(m_peer.IsInvalid(), "'Remote' attribute not properly set");
158
159 if (!m_local.IsInvalid())
160 {
165 "Incompatible peer and local address IP version");
166 ret = m_socket->Bind(m_local);
167 }
168 else
169 {
171 {
172 ret = m_socket->Bind6();
173 }
175 {
176 ret = m_socket->Bind();
177 }
178 }
179
180 if (ret == -1)
181 {
182 NS_FATAL_ERROR("Failed to bind socket");
183 }
184
186 {
187 m_socket->SetIpTos(m_tos); // Affects only IPv4 sockets.
188 }
195 if (tcpSocket)
196 {
197 tcpSocket->TraceConnectWithoutContext(
198 "Retransmission",
200 }
201 }
202 if (m_connected)
203 {
204 m_socket->GetSockName(from);
205 SendData(from, m_peer);
206 }
207}
208
209void
210BulkSendApplication::StopApplication() // Called at time specified by Stop
211{
212 NS_LOG_FUNCTION(this);
213
214 if (m_socket)
215 {
216 m_socket->Close();
217 m_connected = false;
218 }
219 else
220 {
221 NS_LOG_WARN("BulkSendApplication found null socket to close in StopApplication");
222 }
223}
224
225// Private helpers
226
227void
229{
230 NS_LOG_FUNCTION(this);
231
232 while (m_maxBytes == 0 || m_totBytes < m_maxBytes)
233 { // Time to send more
234
235 // uint64_t to allow the comparison later.
236 // the result is in a uint32_t range anyway, because
237 // m_sendSize is uint32_t.
238 uint64_t toSend = m_sendSize;
239 // Make sure we don't send too many
240 if (m_maxBytes > 0)
241 {
242 toSend = std::min(toSend, m_maxBytes - m_totBytes);
243 }
244
245 NS_LOG_LOGIC("sending packet at " << Simulator::Now());
246
247 Ptr<Packet> packet;
248 if (m_unsentPacket)
249 {
250 packet = m_unsentPacket;
251 toSend = packet->GetSize();
252 }
254 {
255 SeqTsSizeHeader header;
256 header.SetSeq(m_seq++);
257 header.SetSize(toSend);
258 NS_ABORT_IF(toSend < header.GetSerializedSize());
259 packet = Create<Packet>(toSend - header.GetSerializedSize());
260 // Trace before adding header, for consistency with PacketSink
261 m_txTraceWithSeqTsSize(packet, from, to, header);
262 packet->AddHeader(header);
263 }
264 else
265 {
266 packet = Create<Packet>(toSend);
267 }
268
269 int actual = m_socket->Send(packet);
270 if ((unsigned)actual == toSend)
271 {
272 m_totBytes += actual;
273 m_txTrace(packet);
274 m_unsentPacket = nullptr;
275 }
276 else if (actual == -1)
277 {
278 // We exit this loop when actual < toSend as the send side
279 // buffer is full. The "DataSent" callback will pop when
280 // some buffer space has freed up.
281 NS_LOG_DEBUG("Unable to send packet; caching for later attempt");
282 m_unsentPacket = packet;
283 break;
284 }
285 else if (actual > 0 && (unsigned)actual < toSend)
286 {
287 // A Linux socket (non-blocking, such as in DCE) may return
288 // a quantity less than the packet size. Split the packet
289 // into two, trace the sent packet, save the unsent packet
290 NS_LOG_DEBUG("Packet size: " << packet->GetSize() << "; sent: " << actual
291 << "; fragment saved: " << toSend - (unsigned)actual);
292 Ptr<Packet> sent = packet->CreateFragment(0, actual);
293 Ptr<Packet> unsent = packet->CreateFragment(actual, (toSend - (unsigned)actual));
294 m_totBytes += actual;
295 m_txTrace(sent);
296 m_unsentPacket = unsent;
297 break;
298 }
299 else
300 {
301 NS_FATAL_ERROR("Unexpected return value from m_socket->Send ()");
302 }
303 }
304 // Check if time to close (all sent)
306 {
307 m_socket->Close();
308 m_connected = false;
309 }
310}
311
312void
314{
315 NS_LOG_FUNCTION(this << socket);
316 NS_LOG_LOGIC("BulkSendApplication Connection succeeded");
317 m_connected = true;
318 Address from;
319 Address to;
320 socket->GetSockName(from);
321 socket->GetPeerName(to);
322 SendData(from, to);
323}
324
325void
327{
328 NS_LOG_FUNCTION(this << socket);
329 NS_LOG_LOGIC("BulkSendApplication, Connection Failed");
330}
331
332void
334{
335 NS_LOG_FUNCTION(this);
336
337 if (m_connected)
338 { // Only send new data if the connection has completed
339 Address from;
340 Address to;
341 socket->GetSockName(from);
342 socket->GetPeerName(to);
343 SendData(from, to);
344 }
345}
346
347void
349 const TcpHeader& header,
350 const Address& localAddr,
351 const Address& peerAddr,
353{
354 NS_LOG_FUNCTION(this << p << header << localAddr << peerAddr << socket);
355 m_retransmissionTrace(p, header, localAddr, peerAddr, socket);
356}
357
358} // Namespace ns3
a polymophic address class
Definition address.h:90
bool IsInvalid() const
Definition address.cc:60
The base class for all ns3 applications.
Definition application.h:51
void DoDispose() override
Destructor implementation.
Ptr< Node > GetNode() const
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 PacketRetransmitted(Ptr< const Packet > p, const TcpHeader &header, const Address &localAddr, const Address &peerAddr, Ptr< const TcpSocketBase > socket)
Packet retransmitted (called by TcpSocketBase sockets via callback)
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.
TracedCallback< Ptr< const Packet >, const TcpHeader &, const Address &, const Address &, Ptr< const TcpSocketBase > > m_retransmissionTrace
Traced Callback: retransmitted packets.
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.
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:197
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:76
void SetIpTos(uint8_t ipTos)
Manually set IP Type of Service field.
Definition socket.cc:423
virtual int ShutdownRecv()=0
virtual int Bind6()=0
Allocate a local IPv6 endpoint for this socket.
@ NS3_SOCK_STREAM
Definition socket.h:97
@ NS3_SOCK_SEQPACKET
Definition socket.h:98
void SetSendCallback(Callback< void, Ptr< Socket >, uint32_t > sendCb)
Notify application when space in transmit buffer is added.
Definition socket.cc:110
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:61
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
Header for the Transmission Control Protocol.
Definition tcp-header.h:36
static TypeId GetTypeId()
Get the type ID.
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Hold an unsigned integer type.
Definition uinteger.h:34
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
Definition abort.h:97
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition abort.h:65
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
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:113
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
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:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeChecker > MakeAddressChecker()
Definition address.cc:169
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition type-id.cc:1320
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
Ptr< const AttributeAccessor > MakeAddressAccessor(T1 a1)
Definition address.h:275
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition type-id.h:617