5G-LENA nr-v4.0
The 5G/NR module for the ns-3 simulator
Loading...
Searching...
No Matches
traffic-generator.cc
Go to the documentation of this file.
1// Copyright (c) 2010 Georgia Institute of Technology
2// Copyright (c) 2022 CTTC
3// Copyright (c) 2023 Centre Tecnologic de Telecomunicacions de Catalunya (CTTC)
4//
5// SPDX-License-Identifier: GPL-2.0-only
6
7#include "traffic-generator.h"
8
9#include "ns3/address.h"
10#include "ns3/log.h"
11#include "ns3/node.h"
12#include "ns3/nstime.h"
13#include "ns3/packet.h"
14#include "ns3/simulator.h"
15#include "ns3/socket-factory.h"
16#include "ns3/socket.h"
17#include "ns3/tcp-socket-factory.h"
18#include "ns3/trace-source-accessor.h"
19#include "ns3/udp-socket-factory.h"
20#include "ns3/uinteger.h"
21
22namespace ns3
23{
24
25NS_LOG_COMPONENT_DEFINE("TrafficGenerator");
26NS_OBJECT_ENSURE_REGISTERED(TrafficGenerator);
27
28uint16_t TrafficGenerator::m_tgIdCounter = 0;
29
30TypeId
32{
33 static TypeId tid =
34 TypeId("ns3::TrafficGenerator").SetParent<Application>().SetGroupName("Applications");
35 return tid;
36}
37
38TrafficGenerator::TrafficGenerator()
39 : Application(),
40 m_socket(nullptr),
41 m_connected(false),
42 m_currentBurstTotBytes(0),
43 m_currentBurstTotPackets(0),
44 m_totBytes(0),
45 m_totPackets(0),
46 m_stopped(false)
47{
48 NS_LOG_FUNCTION(this);
49 m_tgId = m_tgIdCounter++;
50}
51
52TrafficGenerator::~TrafficGenerator()
53{
54 NS_LOG_FUNCTION(this);
55}
56
57uint64_t
59{
60 NS_LOG_FUNCTION(this);
61 return m_totBytes;
62}
63
64uint64_t
66{
67 NS_LOG_FUNCTION(this);
68 return m_totPackets;
69}
70
71Ptr<Socket>
73{
74 NS_LOG_FUNCTION(this);
75 return m_socket;
76}
77
78void
79TrafficGenerator::GenerateNextPacketBurstSize()
80{
81 NS_LOG_FUNCTION(this);
82 m_packetBurstSizeInBytes = 0;
83 m_packetBurstSizeInPackets = 0;
84}
85
86void
87TrafficGenerator::DoDispose()
88{
89 NS_LOG_FUNCTION(this);
90 m_socket = nullptr;
91 // chain up
92 Application::DoDispose();
93}
94
95void
96TrafficGenerator::DoInitialize()
97{
98 NS_LOG_FUNCTION(this);
99 Application::DoInitialize();
100}
101
102bool
104{
105 NS_LOG_FUNCTION(this);
106
107 m_waitForNextPacketBurst = false;
108
109 if (m_stopped)
110 {
111 NS_LOG_INFO("Ignore SendPacketBurst because the application is stopped.");
112 return false;
113 }
114
115 m_currentBurstTotBytes = 0;
116 m_currentBurstTotPackets = 0;
117
118 if (m_socket)
119 {
120 NS_LOG_FUNCTION("Socket exists");
121 }
122 else
123 {
124 m_socket = Socket::CreateSocket(GetNode(), m_tid);
125 if (Inet6SocketAddress::IsMatchingType(m_peer))
126 {
127 m_socket->Bind6();
128 }
129 else if (InetSocketAddress::IsMatchingType(m_peer))
130 {
131 m_socket->Bind();
132 }
133 else
134 {
135 NS_LOG_UNCOND("Could not bind the socket.");
136 }
137 int connectRes = m_socket->Connect(m_peer);
138 NS_ABORT_MSG_UNLESS(connectRes == 0,
139 "Error in connecting the socket to the peer address:" << m_peer);
140 m_socket->ShutdownRecv();
141 m_socket->SetConnectCallback(MakeCallback(&TrafficGenerator::ConnectionSucceeded, this),
142 MakeCallback(&TrafficGenerator::ConnectionFailed, this));
143 m_socket->SetSendCallback(MakeCallback(&TrafficGenerator::SendNextPacketIfConnected, this));
144 m_socket->SetCloseCallbacks(MakeCallback(&TrafficGenerator::CloseSucceeded, this),
145 MakeCallback(&TrafficGenerator::CloseFailed, this));
146 }
147
148 if (m_connected || m_tid == UdpSocketFactory::GetTypeId())
149 {
150 GenerateNextPacketBurstSize();
151
152 if (m_packetBurstSizeInBytes != 0)
153 {
154 NS_LOG_LOGIC("Starting transfer of packet burst of size " << m_packetBurstSizeInBytes);
155 }
156 else
157 {
158 NS_LOG_LOGIC(
159 "Starting transfer of packet burst of unknown size, that will contain at least: "
160 << m_packetBurstSizeInPackets << " packets");
161 }
162
163 // If the event is running cancel it since we call directly the first packet of the packet
164 // burst
165 if (m_eventIdSendNextPacket.IsPending())
166 {
167 m_eventIdSendNextPacket.Cancel();
168 NS_LOG_WARN("Canceling next packet send");
169 }
170 SendNextPacket();
171 }
172 else
173 {
174 NS_LOG_UNCOND(this << " Not connected yet. Expected if you are using TCP socket because "
175 "TCP handshake needs to complete...");
176 }
177
178 return true;
179}
180
181// Application Methods
182void
183TrafficGenerator::StartApplication() // Called at time specified by Start
184{
185 NS_LOG_FUNCTION(this);
186}
187
188void
189TrafficGenerator::StopApplication() // Called at time specified by Stop
190{
191 NS_LOG_FUNCTION(this);
192 NS_LOG_LOGIC("TrafficGenerator closing socket");
193
194 if (!(m_connected || m_tid == UdpSocketFactory::GetTypeId()))
195 {
196 NS_LOG_WARN("Stopping the application that never started. Which could happen if the "
197 "protocol used is TCP and the connection never got established.");
198 }
199
200 // so that if any event is being scheduled to cancel it
201 m_stopped = true;
202
203 if (!m_socket)
204 {
205 NS_LOG_WARN("TrafficGenerator found null socket to close in StopApplication");
206 return;
207 }
208
209 if (m_tid == UdpSocketFactory::GetTypeId())
210 {
211 m_socket = nullptr;
212 }
213 else
214 {
215 m_socket->Close();
216 m_connected = false;
217 m_socket = nullptr;
218 }
219
220 NS_LOG_INFO("Sent packets: " << m_totPackets << " and the total bytes: " << m_totBytes);
221}
222
223void
224TrafficGenerator::SetPacketBurstSizeInBytes(uint32_t burstSize)
225{
226 m_packetBurstSizeInBytes = burstSize;
227}
228
229void
230TrafficGenerator::SetPacketBurstSizeInPackets(uint32_t burstSize)
231{
232 m_packetBurstSizeInPackets = burstSize;
233}
234
235uint32_t
236TrafficGenerator::GetPacketBurstSizeInBytes() const
237{
238 return m_packetBurstSizeInBytes;
239}
240
241uint32_t
242TrafficGenerator::GetPacketBurstSizeInPackets() const
243{
244 return m_packetBurstSizeInPackets;
245}
246
247void
248TrafficGenerator::SendNextPacket()
249{
250 if (m_stopped)
251 {
252 NS_LOG_WARN("Ignore SendNextPacket because the application is stopped.");
253 return;
254 }
255 if (!m_socket)
256 {
257 NS_LOG_DEBUG("Socket closed. Ignoring the call for send next packet.");
258 return;
259 }
260
261 if (m_packetBurstSizeInBytes == 0 && m_packetBurstSizeInPackets == 0)
262 {
263 GenerateNextPacketBurstSize();
264 }
265
266 NS_ASSERT(m_packetBurstSizeInBytes || m_packetBurstSizeInPackets);
267
268 // Time to send more
269 uint32_t toSend = GetNextPacketSize();
270 // Make sure we don't send too many
271 if ((m_packetBurstSizeInBytes > 0) and
272 (m_packetBurstSizeInBytes - m_currentBurstTotBytes > toSend))
273 {
274 toSend = std::min(toSend, m_packetBurstSizeInBytes - m_currentBurstTotBytes);
275 NS_LOG_INFO("Sending a packet at " << Simulator::Now() << " of size:" << toSend);
276 //<< ", and left to send: " << (m_packetBurstSizeInBytes - m_currentBurstTotBytes));
277 }
278 NS_ASSERT(toSend);
279 int actual = 0;
280 /*
281 XrHeader xrHeader (GetTrafficType());
282 if (m_socket->GetTxAvailable() > toSend + xrHeader.GetSerializedSize ())
283 */
284 if (m_socket->GetTxAvailable() > toSend)
285 {
286 Ptr<Packet> packet = Create<Packet>(toSend);
287 m_txTrace(packet);
288 actual = m_socket->Send(packet);
289 // NS_ASSERT (actual == (int) (toSend + xrHeader.GetSerializedSize ()));
290 NS_ASSERT(actual == (int)(toSend));
291 }
292 else
293 {
294 NS_ABORT_MSG_IF(
295 m_tid == UdpSocketFactory::GetTypeId(),
296 "When using UDP socket the packet size cannot be greater than 65535, reconfigure your "
297 "application to generate packets up to this permitted size.");
298 // it may happen that the buffer is full
299 NS_LOG_WARN("Unable to send packet; actual " << actual << " size " << toSend
300 << "; caching for later attempt");
301 }
302 NS_LOG_INFO("Sent data: " << actual << " bytes.");
303
304 if ((actual < (int)toSend))
305 {
306 // We exit this loop when actual < toSend as the send side
307 // buffer is full. The "DataSent" callback will pop when
308 // some buffer space has freed ip.
309 NS_LOG_DEBUG("Send buffer is full.");
310 return;
311 }
312 else
313 {
314 m_currentBurstTotBytes += actual;
315 m_totBytes += actual;
316 m_currentBurstTotPackets++;
317 m_totPackets++;
318 NS_LOG_INFO("Sending " << actual
319 << " bytes. "
320 "Total bytes: "
321 << m_currentBurstTotBytes
322 << ", and packetBurstSize: " << m_packetBurstSizeInBytes);
323 }
324
325 if (m_currentBurstTotBytes < m_packetBurstSizeInBytes ||
326 m_currentBurstTotPackets < m_packetBurstSizeInPackets || m_packetBurstSizeInPackets == 1)
327 {
328 Time nextPacketTime = GetNextPacketTime();
329 NS_ASSERT(nextPacketTime.GetSeconds() >= 0);
330 m_eventIdSendNextPacket =
331 Simulator::Schedule(nextPacketTime, &TrafficGenerator::SendNextPacket, this);
332 }
333 else // we finished transmitting this packet burst
334 {
335 m_currentBurstTotBytes = 0;
336 m_currentBurstTotPackets = 0;
337 m_eventIdSendNextPacket.Cancel();
338 m_waitForNextPacketBurst = true;
339 PacketBurstSent();
340 }
341}
342
343void
344TrafficGenerator::PacketBurstSent()
345{
346 NS_LOG_FUNCTION(this);
347}
348
349Time
350TrafficGenerator::GetNextPacketTime() const
351{
352 NS_LOG_FUNCTION(this);
353 return MilliSeconds(0);
354}
355
356void
357TrafficGenerator::ConnectionSucceeded(Ptr<Socket> socket)
358{
359 NS_LOG_FUNCTION(this << socket);
360 NS_LOG_UNCOND(this << " TrafficGenerator Connection succeeded");
361 m_connected = true;
362
363 // Only if the event is not running scheule it
364 if (!m_eventIdSendNextPacket.IsPending() && !m_waitForNextPacketBurst)
365 {
366 Time nextPacketTime = GetNextPacketTime();
367 m_eventIdSendNextPacket =
368 Simulator::Schedule(nextPacketTime, &TrafficGenerator::SendNextPacket, this);
369 }
370}
371
372void
373TrafficGenerator::ConnectionFailed(Ptr<Socket> socket)
374{
375 NS_LOG_FUNCTION(this << socket);
376 NS_LOG_LOGIC("TrafficGenerator Connection failed");
377 m_socket->Close();
378}
379
380void
381TrafficGenerator::CloseSucceeded(Ptr<Socket> socket)
382{
383 NS_LOG_FUNCTION(this << socket);
384 NS_LOG_LOGIC("TrafficGenerator Close succeeded");
385 m_socket = nullptr;
386}
387
388void
389TrafficGenerator::CloseFailed(Ptr<Socket> socket)
390{
391 NS_LOG_FUNCTION(this << socket);
392 NS_LOG_LOGIC("TrafficGenerator Close failed");
393 m_socket = nullptr;
394}
395
396void
397TrafficGenerator::SendNextPacketIfConnected(Ptr<Socket>, uint32_t)
398{
399 NS_LOG_FUNCTION(this);
400 if (m_socket)
401 {
402 if (m_connected || m_tid == UdpSocketFactory::GetTypeId())
403 { // Only send new data if the connection has completed
404 NS_LOG_LOGIC("TrafficGenerator SendNextPacketIfConnected callback triggers new "
405 "SendNextPacket call");
406 // Only if the event is not running scheule it
407 if (!m_eventIdSendNextPacket.IsPending() && !m_waitForNextPacketBurst)
408 {
409 Time nextPacketTime = GetNextPacketTime();
410 m_eventIdSendNextPacket =
411 Simulator::Schedule(nextPacketTime, &TrafficGenerator::SendNextPacket, this);
412 }
413 }
414 }
415}
416
417void
419{
420 m_peer = remote;
421}
422
423void
425{
426 m_tid = protocol;
427}
428
429uint16_t
430TrafficGenerator::GetTgId() const
431{
432 return m_tgId;
433}
434
435Address
436TrafficGenerator::GetPeer() const
437{
438 return m_peer;
439}
440
441int64_t
443{
444 return 0;
445}
446
447} // Namespace ns3
uint64_t GetTotalPackets() const
Get the total number of packets that have been sent during this object's lifetime.
void SetRemote(Address remote)
Sets the remote address.
static TypeId GetTypeId()
Get the type ID.
bool SendPacketBurst()
Send another packet burst, which can be e.g., a file, or a video frame.
int64_t AssignStreams(int64_t stream) override
void SetProtocol(TypeId protocol)
Sets the protocol.
uint64_t GetTotalBytes() const
Get the total number of bytes that have been sent during this object's lifetime.
Ptr< Socket > GetSocket() const
Get the socket this application is attached to.