A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
tgax-voip-example.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006,2007 INRIA
3 * Copyright (c) 2016 Magister Solutions
4 * Copyright (c) 2025 Tom Henderson
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 * Borrows from examples/wireless/wifi-ap.cc for overall Wi-Fi network setup pattern
9 * Borrows from src/applications/examples/three-gpp-http-example.cc for overall simulation flow
10 */
11
12/**
13 * @file tgax-voip-example.cc
14 * @brief A simple VoIP traffic generator example over Wi-Fi
15 *
16 * This example demonstrates how to set up a basic ns-3 simulation with VoIP traffic
17 * over a Wi-Fi network. It includes three configurations:
18 *
19 * 1. IPv4/UDP: VoIP traffic over IPv4 using UDP sockets
20 * 2. IPv6/UDP: VoIP traffic over IPv6 using UDP sockets
21 * 3. PacketSocket: VoIP traffic using raw packet sockets
22 *
23 * The simulation consists of:
24 * - A simple Wi-Fi network with one AP (Access Point) and one STA (Station)
25 * - VoIP traffic flowing from the STA to the AP
26 * - Application-level tracing to observe VoIP packets being sent
27 * - State change tracing to see voice activity transitions
28 *
29 * To run with IPv4/UDP (default): ./ns3 run tgax-voip-example
30 * To run with IPv6/UDP: ./ns3 run "tgax-voip-example --socketType=ipv6"
31 * To run with PacketSocket: ./ns3 run "tgax-voip-example --socketType=packet"
32 *
33 * To disable verbose logging: ./ns3 run "tgax-voip-example --verbose=false"
34 */
35
36#include "ns3/applications-module.h"
37#include "ns3/core-module.h"
38#include "ns3/internet-module.h"
39#include "ns3/mobility-module.h"
40#include "ns3/network-module.h"
41#include "ns3/wifi-module.h"
42
43using namespace ns3;
44
45NS_LOG_COMPONENT_DEFINE("TgaxVoipExample");
46
47/**
48 * Callback invoked when a VoIP packet is transmitted
49 * @param packet The transmitted packet
50 * @param jitter The jitter applied to the packet
51 */
52void VoipPacketSent(Ptr<const Packet> packet, Time jitter);
53/**
54 * Callback invoked when the VoIP application state changes (active/silence)
55 * @param state The new voice activity state
56 * @param duration The expected duration in this state
57 */
59/**
60 * Callback invoked when the PacketSink receives a packet
61 * @param context The context string
62 * @param packet The received packet
63 * @param address The sender's address
64 */
65void PacketReceived(std::string context, Ptr<const Packet> packet, const Address& address);
66
67int
68main(int argc, char* argv[])
69{
70 Time duration{Seconds(10)}; // Simulation time in seconds
71 std::string socketType{"ipv4"}; // Socket type: ipv4, ipv6, or packet
72 bool verbose = true; // Enable/disable verbose logging
73
74 CommandLine cmd(__FILE__);
75 cmd.Usage("Basic VoIP example");
76 cmd.AddValue("duration", "Duration of traffic flow, in seconds", duration);
77 cmd.AddValue("socketType",
78 "Socket type to use (ipv4, ipv6, or packet). Default: ipv4",
79 socketType);
80 cmd.AddValue("verbose",
81 "Enable verbose logging of TgaxVoipTraffic, PacketSink, and this program",
82 verbose);
83 cmd.Parse(argc, argv);
84
85 if (verbose)
86 {
88 "TgaxVoipExample",
91 "TgaxVoipTraffic",
94 "PacketSink",
96 }
97
98 NodeContainer wifiNodes;
99 wifiNodes.Create(2); // Create 2 nodes: one will be AP, one will be STA
100
101 Ptr<Node> apNode = wifiNodes.Get(0);
102 Ptr<Node> staNode = wifiNodes.Get(1);
103
106 phy.SetChannel(channel.Create());
107
110 wifi.SetStandard(WIFI_STANDARD_80211ax);
111
112 NetDeviceContainer wifiDevices;
113
114 // Configure AP
115 Ssid ssid = Ssid("voip-network");
116 mac.SetType("ns3::ApWifiMac", "Ssid", SsidValue(ssid));
117 auto apDevices = wifi.Install(phy, mac, apNode);
118 wifiDevices.Add(apDevices);
119
120 // Configure STA
121 mac.SetType("ns3::StaWifiMac", "Ssid", SsidValue(ssid));
122 auto staDevices = wifi.Install(phy, mac, staNode);
123 wifiDevices.Add(staDevices);
124
126 mobility.SetPositionAllocator("ns3::GridPositionAllocator",
127 "MinX",
128 DoubleValue(0.0),
129 "MinY",
130 DoubleValue(0.0),
131 "DeltaX",
132 DoubleValue(5.0),
133 "DeltaY",
134 DoubleValue(5.0),
135 "GridWidth",
136 UintegerValue(2),
137 "LayoutType",
138 StringValue("RowFirst"));
139 mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
140 mobility.Install(wifiNodes);
141
143 internet.Install(wifiNodes);
144
146 Ipv4InterfaceContainer ipv4Interfaces;
148 Ipv6InterfaceContainer ipv6Interfaces;
149
150 if (socketType == "ipv4")
151 {
152 // Assign IPv4 addresses (needed even for IPv6-only test for basic network function)
153 ipv4.SetBase("10.1.1.0", "255.255.255.0");
154 ipv4Interfaces = ipv4.Assign(wifiDevices);
155 NS_LOG_INFO("AP address: 10.1.1.1");
156 NS_LOG_INFO("STA address: 10.1.1.2");
157 }
158 else if (socketType == "ipv6")
159 {
160 // Assign IPv6 addresses
161 ipv6.SetBase("2001:db8::", Ipv6Prefix(64));
162 ipv6Interfaces = ipv6.Assign(wifiDevices);
163 NS_LOG_INFO("AP address: 2001:db8::1");
164 NS_LOG_INFO("STA address: 2001:db8::2");
165 }
166
167 std::string protocol;
168 std::string remoteAddress;
169 uint16_t remotePort = 5000;
170
171 if (socketType == "ipv4")
172 {
173 protocol = "ns3::UdpSocketFactory";
174 remoteAddress = "10.1.1.1"; // AP's IPv4 address
175 }
176 else if (socketType == "ipv6")
177 {
178 protocol = "ns3::UdpSocketFactory";
179 remoteAddress = "2001:db8::1"; // AP's IPv6 address
180 }
181 else if (socketType == "packet")
182 {
183 protocol = "ns3::PacketSocketFactory";
184 }
185 else
186 {
187 NS_FATAL_ERROR("Invalid socket type: " << socketType);
188 }
189
191
192 // Configure VoIP parameters
193 // These are the IEEE 802.11ax TGAX defaults:
194 // - Active state: 33-byte payload at 20ms intervals
195 // - Silence state: 7-byte payload at 160ms intervals
196 // - State transitions: 2-state Markov model with 50% voice activity
197 // - Jitter: Laplacian distribution (downlink only)
198
199 // For IPv4/UDP, add 3 bytes for compressed protocol header to payload sizes
200 // For IPv6/UDP, add 5 bytes for compressed protocol header to payload sizes
201 // For PacketSocket, use default sizes
202 uint32_t activePayloadSize = 33;
204
205 if (socketType == "ipv4")
206 {
207 // IPv4 header compression adds 3 bytes
208 activePayloadSize += 3;
210 }
211 else if (socketType == "ipv6")
212 {
213 // IPv6 header compression adds 5 bytes
214 activePayloadSize += 5;
216 }
217
218 sourceHelper.SetAttribute("Protocol", StringValue(protocol));
219 sourceHelper.SetAttribute("ActivePacketPayloadSize", UintegerValue(activePayloadSize));
220 sourceHelper.SetAttribute("SilencePacketPayloadSize", UintegerValue(silencePayloadSize));
221
222 // Optional: Configure VoIP state machine parameters
223 // Uncomment to customize:
224 // sourceHelper.SetAttribute("MeanActiveStateDuration", TimeValue(MilliSeconds(1250)));
225 // sourceHelper.SetAttribute("MeanInactiveStateDuration", TimeValue(MilliSeconds(1250)));
226 // sourceHelper.SetAttribute("VoiceToSilenceProbability", DoubleValue(0.016));
227 // sourceHelper.SetAttribute("SilenceToVoiceProbability", DoubleValue(0.016));
228
229 // Set remote address and port based on socket type
230 Address remoteAddr;
231 if (socketType == "ipv4")
232 {
233 remoteAddr = InetSocketAddress(Ipv4Address(remoteAddress.c_str()), remotePort);
234 }
235 else if (socketType == "ipv6")
236 {
237 remoteAddr = Inet6SocketAddress(Ipv6Address(remoteAddress.c_str()), remotePort);
238 }
239 else // PacketSocket
240 {
241 PacketSocketAddress socketAddr;
242 socketAddr.SetSingleDevice(staDevices.Get(0)->GetIfIndex());
243 socketAddr.SetPhysicalAddress(apDevices.Get(0)->GetAddress());
244 socketAddr.SetProtocol(1);
245 remoteAddr = socketAddr;
246 }
247
248 sourceHelper.SetAttribute("Remote", AddressValue(remoteAddr));
249
250 // Install VoIP source on STA node
251 auto sourceApps = sourceHelper.Install(staNode);
252 sourceApps.Start(Seconds(1.0));
253 sourceApps.Stop(Seconds(1.0) + duration);
254
255 Address sinkAddr;
256 if (socketType == "ipv4")
257 {
258 sinkAddr = InetSocketAddress(Ipv4Address::GetAny(), remotePort);
259 }
260 else if (socketType == "ipv6")
261 {
262 sinkAddr = Inet6SocketAddress(Ipv6Address::GetAny(), remotePort);
263 }
264 else // PacketSocket
265 {
266 PacketSocketAddress socketAddr;
267 socketAddr.SetSingleDevice(apDevices.Get(0)->GetIfIndex());
268 socketAddr.SetPhysicalAddress(apDevices.Get(0)->GetAddress());
269 socketAddr.SetProtocol(1);
270 sinkAddr = socketAddr;
271 }
272
273 PacketSinkHelper sinkHelper(protocol, sinkAddr);
274 auto sinkApps = sinkHelper.Install(apNode);
275 sinkApps.Start(Seconds(0.0));
276 sinkApps.Stop(Seconds(2.0) + duration);
277
278 NS_LOG_INFO("PacketSink application installed on AP (Node 0)");
279
280 // Connect to VoIP TX with jitter trace
282 "/NodeList/*/ApplicationList/*/$ns3::TgaxVoipTraffic/TxWithJitter",
284
285 // Connect to VoIP state change trace
286 Config::ConnectWithoutContext("/NodeList/*/ApplicationList/*/$ns3::TgaxVoipTraffic/StateUpdate",
288
289 // Connect to RX trace
290 Config::Connect("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx",
292
293 NS_LOG_INFO("Starting simulation for traffic duration: " << duration.As(Time::S));
294 NS_LOG_INFO("Socket type: " << socketType);
295 NS_LOG_INFO("Active payload size: " << activePayloadSize << " bytes");
296 NS_LOG_INFO("Silence payload size: " << silencePayloadSize << " bytes");
297
298 Simulator::Stop(Seconds(2) + duration);
300
301 // Get the packet sink application to retrieve statistics
303 if (sink)
304 {
305 uint32_t totalBytes = sink->GetTotalRx();
306 NS_LOG_INFO("Total bytes received: " << totalBytes);
307
308 // Calculate approximate statistics for default configuration
309 // Active packets: ~36 bytes every 20ms = 1800 bytes per second (1 second of talking)
310 // Silence packets: ~10 bytes every 160ms = 62.5 bytes per second (1 second of silence)
311 // With 50% voice activity: average = (1800 + 62.5) / 2 = ~931 bytes per second
312 // For default 10 seconds of simulation, this is 9310 bytes. Users can observe
313 // variation of the actual bytes sent by varying the RngRun parameter to use
314 // different random variable run numbers. Because the duration of this test is short
315 // by default (10 seconds), the difference between actual and expected will vary but
316 // will gradually converge as traffic duration time is increased.
317 // Note that if you change the default configuration of the model, the below estimate
318 // will not update accordingly.
319 NS_LOG_INFO("Approximate expected bytes (50% activity): " << 931 * duration.GetSeconds());
320 }
321
323
324 return 0;
325}
326
327void
329{
330 NS_LOG_INFO("VoIP TX: " << " Packet size (bytes): " << packet->GetSize()
331 << " Jitter: " << jitter.As(Time::US));
332}
333
334void
336{
337 std::string stateStr = (state == TgaxVoipTraffic::VoiceActivityState::ACTIVE_TALKING)
338 ? "ACTIVE_TALKING"
339 : "INACTIVE_SILENCE";
340 NS_LOG_INFO("VoIP State: " << stateStr << " Duration: " << duration.As(Time::MS));
341}
342
343void
344PacketReceived(std::string context, Ptr<const Packet> packet, const Address& address)
345{
346 NS_LOG_INFO("Packet RX: Size(bytes): " << packet->GetSize());
347}
a polymophic address class
Definition address.h:114
AttributeValue implementation for Address.
Definition address.h:329
A helper to make it easier to instantiate an application on a set of nodes.
Parse command-line arguments.
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition double.h:31
An Inet6 address class.
an Inet address class
aggregate IP/TCP/UDP functionality to existing Nodes.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
Ipv4 addresses are stored in host order in this class.
static Ipv4Address GetAny()
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Helper class to auto-assign global IPv6 unicast addresses.
void SetBase(Ipv6Address network, Ipv6Prefix prefix, Ipv6Address base=Ipv6Address("::1"))
Set the base network number, network prefix, and base interface ID.
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses.
Describes an IPv6 address.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
Keep track of a set of IPv6 interfaces.
Describes an IPv6 prefix.
Helper class used to assign positions and mobility models to nodes.
holds a vector of ns3::NetDevice pointers
void Add(NetDeviceContainer other)
Append the contents of another NetDeviceContainer to the end of this container.
keep track of a set of node pointers.
void Create(uint32_t n)
Create n nodes and append pointers to them to the end of this NodeContainer.
Ptr< Node > Get(uint32_t i) const
Get the Ptr<Node> stored in this container at a given index.
A helper to make it easier to instantiate an ns3::PacketSinkApplication on a set of nodes.
an address for a packet socket
void SetProtocol(uint16_t protocol)
Set the protocol.
void SetPhysicalAddress(const Address address)
Set the destination address.
void SetSingleDevice(uint32_t device)
Set the address to match only a specified NetDevice.
Smart pointer class similar to boost::intrusive_ptr.
Definition ptr.h:70
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:125
static void Run()
Run the simulation.
Definition simulator.cc:161
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition simulator.cc:169
The IEEE 802.11 SSID Information Element.
Definition ssid.h:25
AttributeValue implementation for Ssid.
Definition ssid.h:85
Hold variables of type string.
Definition string.h:45
VoiceActivityState
Voice activity states.
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition nstime.h:95
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:408
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:398
@ US
microsecond
Definition nstime.h:108
@ MS
millisecond
Definition nstime.h:107
@ S
second
Definition nstime.h:106
Hold an unsigned integer type.
Definition uinteger.h:34
helps to create WifiNetDevice objects
create MAC layers for a ns3::WifiNetDevice.
manage and create wifi channel objects for the YANS model.
static YansWifiChannelHelper Default()
Create a channel helper in a default working state.
Make it easy to create and manage PHY objects for the YANS model.
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:690
void Connect(std::string path, const CallbackBase &cb)
Definition config.cc:970
void ConnectWithoutContext(std::string path, const CallbackBase &cb)
Definition config.cc:946
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:194
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:267
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1273
@ WIFI_STANDARD_80211ax
const uint32_t silencePayloadSize
payload size of silence packets in bytes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition log.cc:279
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:605
LogLevel
Logging severity classes and levels.
Definition log.h:86
@ LOG_LEVEL_ALL
Print everything.
Definition log.h:108
@ LOG_PREFIX_FUNC
Prefix all trace prints with function.
Definition log.h:110
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition log.h:111
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition log.h:112
@ LOG_LEVEL_INFO
LOG_INFO and above.
Definition log.h:96
staDevices
Definition third.py:87
ssid
Definition third.py:82
channel
Definition third.py:77
mac
Definition third.py:81
wifi
Definition third.py:84
apDevices
Definition third.py:90
mobility
Definition third.py:92
phy
Definition third.py:78
bool verbose
void PacketReceived(std::string context, Ptr< const Packet > packet, const Address &address)
Callback invoked when the PacketSink receives a packet.
void PacketReceived(std::string context, Ptr< const Packet > packet, const Address &address)
Callback invoked when the PacketSink receives a packet.
void VoipPacketSent(Ptr< const Packet > packet, Time jitter)
Callback invoked when a VoIP packet is transmitted.
void VoipStateChanged(TgaxVoipTraffic::VoiceActivityState state, Time duration)
Callback invoked when the VoIP application state changes (active/silence).
Ptr< PacketSink > sink
Pointer to the packet sink application.
Definition wifi-tcp.cc:44