A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tgax-voip-traffic.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024 DERONNE SOFTWARE ENGINEERING
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Sébastien Deronne <sebastien.deronne@gmail.com>
7 */
8
9#include "tgax-voip-traffic.h"
10
11#include "ns3/double.h"
12#include "ns3/inet-socket-address.h"
13#include "ns3/inet6-socket-address.h"
14#include "ns3/log.h"
15#include "ns3/node.h"
16#include "ns3/nstime.h"
17#include "ns3/packet-socket-address.h"
18#include "ns3/packet.h"
19#include "ns3/random-variable-stream.h"
20#include "ns3/simulator.h"
21#include "ns3/socket-factory.h"
22#include "ns3/socket.h"
23#include "ns3/uinteger.h"
24
25namespace ns3
26{
27
28NS_LOG_COMPONENT_DEFINE("TgaxVoipTraffic");
29
31
34{
35 static TypeId tid =
36 TypeId("ns3::TgaxVoipTraffic")
38 .SetGroupName("Applications")
39 .AddConstructor<TgaxVoipTraffic>()
40 .AddAttribute(
41 "Protocol",
42 "The type of protocol to use. This should be a subclass of ns3::SocketFactory",
43 TypeId::ATTR_GET | TypeId::ATTR_CONSTRUCT, // prevent setting after construction
44 TypeIdValue(TypeId::LookupByName("ns3::PacketSocketFactory")),
47 .AddAttribute(
48 "ActivePacketPayloadSize",
49 "Size in bytes for payload of packets generated during periods of active talking.",
50 UintegerValue(33),
53 .AddAttribute(
54 "SilencePacketPayloadSize",
55 "Size in bytes for payload of packets generated during periods of silence.",
59 .AddAttribute("MeanActiveStateDuration",
60 "Mean duration of active/talking state.",
64 .AddAttribute("MeanInactiveStateDuration",
65 "Mean duration of inactive/silence state.",
69 .AddAttribute("VoiceEncoderInterval",
70 "Interval between generation of voice packets.",
74 .AddAttribute("SilenceEncoderInterval",
75 "Interval between generation of silence packets. "
76 "This implementation requires the value of this attribute to be a "
77 "multiple of VoiceEncoderInterval",
81 .AddAttribute(
82 "VoiceToSilenceProbability",
83 "The probability to transition from active talking state to silence state.",
84 DoubleValue(0.016),
87 .AddAttribute(
88 "SilenceToVoiceProbability",
89 "The probability to transition from silence state to active talking state.",
90 DoubleValue(0.016),
93 .AddAttribute("ScaleDelayJitter",
94 "Scale of laplacian distribution used to calculate delay jitter for "
95 "generated packets.",
99 .AddAttribute("BoundDelayJitter",
100 "Bound of laplacian distribution used to calculate delay jitter for "
101 "generated packets. For no jitter, set this attribute to zero.",
105 .AddTraceSource(
106 "TxWithJitter",
107 "A VoIP packet is sent, this trace also reports the jitter applied to the packet",
109 "ns3::TgaxVoipTraffic::TxTracedCallback")
110 .AddTraceSource("StateUpdate",
111 "Voice activity state updated",
113 "ns3::TgaxVoipTraffic::StateUpdatedCallback");
114 return tid;
115}
116
126
131
132int64_t
134{
135 NS_LOG_FUNCTION(this << stream);
136 auto currentStream = stream;
137 m_inactiveExponential->SetStream(currentStream++);
138 m_activeExponential->SetStream(currentStream++);
139 m_inactiveUniform->SetStream(currentStream++);
140 m_activeUniform->SetStream(currentStream++);
141 m_delayJitterLaplacian->SetStream(currentStream++);
142 return (currentStream - stream);
143}
144
145void
147{
148 NS_LOG_FUNCTION(this);
150 m_delayJitterLaplacian->SetAttribute("Scale",
151 DoubleValue(m_delayJitterScale.GetMicroSeconds()));
152 m_delayJitterLaplacian->SetAttribute("Bound",
153 DoubleValue(m_delayJitterBound.GetMicroSeconds()));
154}
155
156void
158{
159 NS_LOG_FUNCTION(this << mean);
160 m_activeExponential->SetAttribute("Mean", DoubleValue(mean.GetMilliSeconds()));
161}
162
163void
165{
166 NS_LOG_FUNCTION(this << mean);
167 m_inactiveExponential->SetAttribute("Mean", DoubleValue(mean.GetMilliSeconds()));
168}
169
170void
172{
173 NS_LOG_FUNCTION(this);
174
175 m_socket->SetAllowBroadcast(true);
176 m_socket->ShutdownRecv();
177
178 if (m_connected)
179 {
180 ScheduleNext();
181 }
182}
183
184void
186{
187 NS_LOG_FUNCTION(this);
188 for (auto& event : m_txPacketEvents)
189 {
190 event.second.Cancel();
191 }
192 m_txPacketEvents.clear();
193 m_stateUpdateEvent.Cancel();
195}
196
197Time
203
204Time
206{
209 "Silence encoder frame duration should be a multiple of voice encoder frame duration");
210 return m_voiceInterval;
211}
212
213void
221
222void
223TgaxVoipTraffic::SendPacket(uint64_t eventId, Ptr<Packet> packet, Time jitter)
224{
225 const auto size = packet->GetSize();
226 NS_LOG_FUNCTION(this << eventId << size << jitter);
227
228 auto it = m_txPacketEvents.find(eventId);
229 NS_ASSERT(it != m_txPacketEvents.end());
230 NS_ASSERT(it->second.IsExpired());
231
232 const auto actualSize = static_cast<uint32_t>(m_socket->Send(packet));
233 NS_ABORT_IF(actualSize != size);
234 m_txTrace(packet);
235 m_txJitterTrace(packet, jitter);
236
238 {
239 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " voip traffic source sent "
240 << size << " bytes to "
241 << InetSocketAddress::ConvertFrom(m_peer).GetIpv4() << " port "
243 }
245 {
246 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S) << " voip traffic source sent "
247 << size << " bytes to "
248 << Inet6SocketAddress::ConvertFrom(m_peer).GetIpv6() << " port "
250 }
251
252 m_txPacketEvents.erase(it);
253}
254
255void
257{
258 NS_LOG_FUNCTION(this);
259
262 NS_ASSERT(!m_remainingEncodingDuration.IsStrictlyNegative());
263
264 auto newState = m_currentState;
266 {
267 if (m_inactiveUniform->GetValue() >= (1 - m_inactiveToActive))
268 {
270 }
271 }
272 else
273 {
274 if (m_activeUniform->GetValue() >= (1 - m_activeToInactive))
275 {
277 }
278 }
280
281 if (!m_remainingStateDuration.IsStrictlyPositive() && m_remainingEncodingDuration.IsZero())
282 {
284 {
288 }
290 ? MilliSeconds(m_activeExponential->GetValue())
291 : MilliSeconds(m_inactiveExponential->GetValue());
293 if ((newState != m_currentState))
294 {
295 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S)
296 << " voip voice activity state changed from " << m_currentState
297 << " to " << newState << " for "
299 m_currentState = newState;
300 }
301 else
302 {
303 NS_LOG_INFO("At time " << Simulator::Now().As(Time::S)
304 << " voip voice activity state unchanged to " << m_currentState
305 << " for " << m_remainingStateDuration.As(Time::MS));
306 }
308 }
309
310 if (m_remainingEncodingDuration.IsZero())
311 {
313 auto delay = GetEncoderFrameDuration();
314 Time jitter{};
315 if (!m_delayJitterBound.IsZero())
316 {
317 jitter = MicroSeconds(static_cast<int64x64_t>(m_delayJitterLaplacian->GetValue()));
318 // Add the bound to always have a positive value as suggested in Robert Novak et al.,
319 // "Downlink VoIP Packet Delay Jitter Model".
320 delay += jitter + m_delayJitterBound;
321 }
322 const auto payloadSize = (m_currentState == VoiceActivityState::ACTIVE_TALKING)
325 auto packet = Create<Packet>(payloadSize);
328 this,
330 packet,
331 jitter);
333 }
334
335 ScheduleNext();
336}
337
338void
344
345std::ostream&
346operator<<(std::ostream& os, TgaxVoipTraffic::VoiceActivityState state)
347{
348 switch (state)
349 {
351 os << "Silence";
352 break;
354 os << "Active talking";
355 break;
356 default:
357 NS_FATAL_ERROR("Unknown voice activity state");
358 }
359 return os;
360}
361
362} // Namespace ns3
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
The exponential distribution Random Number Generator (RNG).
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
static bool IsMatchingType(const Address &addr)
If the address match.
static bool IsMatchingType(const Address &address)
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
The laplacian distribution Random Number Generator (RNG).
virtual void DoInitialize()
Initialize() implementation.
Definition object.cc:437
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:580
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:191
TypeId m_protocolTid
Protocol TypeId value.
SourceApplication(bool allowPacketSocket=true)
Constructor.
Ptr< Socket > m_socket
Socket.
TracedCallback< Ptr< const Packet > > m_txTrace
Traced Callback: transmitted packets.
bool m_connected
flag whether socket is connected
Address m_peer
Peer address.
Generate VoIP traffic.
double m_inactiveToActive
Probability to transition from inactive/silence state to active/talking state.
uint32_t m_activePacketSize
Size in bytes for payload of active packets.
VoiceActivityState m_currentState
Hold the current voice activity state.
Ptr< UniformRandomVariable > m_inactiveUniform
Uniform random variable to generate state transitions from inactive state.
Time m_silenceInterval
Interval between generation of silence packets.
void CancelEvents() override
Cancel all pending events.
TracedCallback< Ptr< const Packet >, Time > m_txJitterTrace
Traced Callback: transmitted packets and their jitters.
Time m_remainingEncodingDuration
The remaining duration to encode the current frame.
TracedCallback< VoiceActivityState, Time > m_stateUpdate
Traced Callback: voice activity state updated.
bool m_pendingStateTransition
Flag whether a state transition should once duration of current state has elapsed.
void ScheduleNext()
Schedule the next state update.
void SendPacket(uint64_t eventId, Ptr< Packet > packet, Time jitter)
Transmit one VoIP packet.
std::map< uint64_t, EventId > m_txPacketEvents
Event IDs of pending TX events.
VoiceActivityState
Voice activity states.
void SetInactiveExponentialMean(Time mean)
Set the mean of the exponential distribution used to calculate durations of inactive/silent state.
static TypeId GetTypeId()
Get the type ID.
Time m_remainingStateDuration
The remaining duration in the current state.
void SetActiveExponentialMean(Time mean)
Set the mean of the exponential distribution used to calculate durations of active/talking state.
Time GetStateUpdateInterval() const
Get the interval between two state updates.
Time m_voiceInterval
Interval between generation of voice packets.
Time GetEncoderFrameDuration() const
Get the duration to encode a frame based on the current state.
void DoConnectionSucceeded(Ptr< Socket > socket) override
Application specific code for child subclasses upon a Connection Succeed event.
Ptr< ExponentialRandomVariable > m_inactiveExponential
Exponential random variable to generate inactive/silent state durations.
uint32_t m_silencePacketSize
Size in bytes for payload of silence packets.
Ptr< ExponentialRandomVariable > m_activeExponential
Exponential random variable to generate active/talking state durations.
Ptr< UniformRandomVariable > m_activeUniform
Uniform random variable to generate state transitions from active state.
int64_t AssignStreams(int64_t stream) override
Assign a fixed random variable stream number to the random variables used by this Application object.
Ptr< LaplacianRandomVariable > m_delayJitterLaplacian
Laplacian random variable to generate delay jitter.
Time m_delayJitterBound
Bound of laplacian distribution used to calculate delay jitter.
uint64_t m_nextEventId
The next event ID.
void DoInitialize() override
Initialize() implementation.
double m_activeToInactive
Probability to transition from active/talking state to inactive/silence state.
void DoStartApplication() override
Application specific startup code for child subclasses.
void UpdateState()
Update voice activity state.
EventId m_stateUpdateEvent
Event ID of pending state update event scheduling.
Time m_delayJitterScale
Scale of laplacian distribution used to calculate delay jitter.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
int64_t GetMilliSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:403
@ MS
millisecond
Definition nstime.h:107
@ S
second
Definition nstime.h:106
AttributeValue implementation for Time.
Definition nstime.h:1375
a unique identifier for an interface.
Definition type-id.h:50
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:870
@ ATTR_GET
The attribute can be read.
Definition type-id.h:55
@ ATTR_CONSTRUCT
The attribute can be written at construction-time.
Definition type-id.h:57
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:999
AttributeValue implementation for TypeId.
Definition type-id.h:649
Hold an unsigned integer type.
Definition uinteger.h:34
The uniform distribution Random Number Generator (RNG).
High precision numerical type, implementing Q64.64 fixed precision.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
Ptr< const AttributeChecker > MakeDoubleChecker()
Definition double.h:82
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition double.h:32
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1376
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1396
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition type-id.cc:1333
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition type-id.h:649
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#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:194
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:627
#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:454
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1307
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1290
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.
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148