To implement Voice over IP (VoIP) in ns3, we have to create an application that simulates VoIP traffic, like VoIP client and server, and which potentially utilizes protocols like RTP for media transport and SIP for session control.
Read the steps for implementing a simple VoIP simulation in ns3.
Prerequisites
- ns3 installation :
make sure that ns3 is installed on your computer.
- C++ Programming :
You should have knowledge in C++.
- Understanding of ns3 :
You should be familiar with ns3 modules and basic simulation scripts.
Steps to implement VoIP in ns3
- Set up your environment
Make sure that ns3 is installed in the computer. If not, install it from the official ns3 website.
- Create a new VoIP module
Go to the src directory in ns3 and create a new directory for your VoIP module.
cd ns-3.XX/src
mkdir voip
cd voip
mkdir model helper test
- Define VoIP classes and header files
In the model directory, create header and implementation files for VoIP.
voip-server.h
#ifndef VOIP_SERVER_H
#define VOIP_SERVER_H
#include “ns3/application.h”
#include “ns3/address.h”
#include “ns3/ptr.h”
#include “ns3/socket.h”
#include “ns3/traced-callback.h”
namespace ns3 {
class VoipServer : public Application {
public:
static TypeId GetTypeId (void);
VoipServer ();
virtual ~VoipServer ();
protected:
virtual void StartApplication (void);
virtual void StopApplication (void);
private:
void HandleRead (Ptr<Socket> socket);
void SendRtpPacket ();
Ptr<Socket> m_socket;
Address m_local;
EventId m_sendEvent;
uint32_t m_packetSize;
uint32_t m_interval;
};
} // namespace ns3
#endif // VOIP_SERVER_H
voip-server.cc
#include “voip-server.h”
#include “ns3/log.h”
#include “ns3/simulator.h”
#include “ns3/inet-socket-address.h”
#include “ns3/uinteger.h”
namespace ns3 {
NS_LOG_COMPONENT_DEFINE (“VoipServer”);
NS_OBJECT_ENSURE_REGISTERED (VoipServer);
TypeId VoipServer::GetTypeId (void) {
static TypeId tid = TypeId (“ns3::VoipServer”)
.SetParent<Application> ()
.SetGroupName (“Applications”)
.AddConstructor<VoipServer> ()
.AddAttribute (“Local”, “The Address on which to Bind the rx socket.”,
AddressValue (),
MakeAddressAccessor (&VoipServer::m_local),
MakeAddressChecker ())
.AddAttribute (“PacketSize”, “The size of packets generated by the VoIP server.”,
UintegerValue (160),
MakeUintegerAccessor (&VoipServer::m_packetSize),
MakeUintegerChecker<uint32_t> ())
.AddAttribute (“Interval”, “The interval between packets generated by the VoIP server.”,
TimeValue (MilliSeconds (20)),
MakeTimeAccessor (&VoipServer::m_interval),
MakeTimeChecker ());
return tid;
}
VoipServer::VoipServer () : m_socket (0) {
NS_LOG_FUNCTION (this);
}
VoipServer::~VoipServer () {
NS_LOG_FUNCTION (this);
}
void VoipServer::StartApplication () {
NS_LOG_FUNCTION (this);
if (m_socket == 0) {
m_socket = Socket::CreateSocket (GetNode (), UdpSocketFactory::GetTypeId ());
m_socket->Bind (m_local);
m_socket->SetRecvCallback (MakeCallback (&VoipServer::HandleRead, this));
}
m_sendEvent = Simulator::Schedule (Seconds (0.0), &VoipServer::SendRtpPacket, this);
}
void VoipServer::StopApplication () {
NS_LOG_FUNCTION (this);
if (m_socket) {
m_socket->Close ();
m_socket->SetRecvCallback (MakeNullCallback<void, Ptr<Socket> > ());
}
Simulator::Cancel (m_sendEvent);
}
void VoipServer::HandleRead (Ptr<Socket> socket) {
NS_LOG_FUNCTION (this << socket);
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom (from))) {
NS_LOG_INFO (“Received request from ” << InetSocketAddress::ConvertFrom (from).GetIpv4 ());
}
}
void VoipServer::SendRtpPacket () {
NS_LOG_FUNCTION (this);
Ptr<Packet> packet = Create<Packet> (m_packetSize); // Create a RTP packet of size m_packetSize
m_socket->Send (packet);
NS_LOG_INFO (“Sent RTP packet”);
m_sendEvent = Simulator::Schedule (MilliSeconds (m_interval), &VoipServer::SendRtpPacket, this);
}
} // namespace ns3
voip-client.h
#ifndef VOIP_CLIENT_H
#define VOIP_CLIENT_H
#include “ns3/application.h”
#include “ns3/address.h”
#include “ns3/ptr.h”
#include “ns3/socket.h”
#include “ns3/traced-callback.h”
namespace ns3 {
class VoipClient : public Application {
public:
static TypeId GetTypeId (void);
VoipClient ();
virtual ~VoipClient ();
protected:
virtual void StartApplication (void);
virtual void StopApplication (void);
private:
void SendRequest ();
void HandleRead (Ptr<Socket> socket);
Ptr<Socket> m_socket;
Address m_peer;
EventId m_sendEvent;
};
} // namespace ns3
#endif // VOIP_CLIENT_H
voip-client.cc
#include “voip-client.h”
#include “ns3/log.h”
#include “ns3/simulator.h”
#include “ns3/inet-socket-address.h”
#include “ns3/uinteger.h”
namespace ns3 {
NS_LOG_COMPONENT_DEFINE (“VoipClient”);
NS_OBJECT_ENSURE_REGISTERED (VoipClient);
TypeId VoipClient::GetTypeId (void) {
static TypeId tid = TypeId (“ns3::VoipClient”)
.SetParent<Application> ()
.SetGroupName (“Applications”)
.AddConstructor<VoipClient> ()
.AddAttribute (“Remote”, “The Address of the VoIP server.”,
AddressValue (),
MakeAddressAccessor (&VoipClient::m_peer),
MakeAddressChecker ());
return tid;
}
VoipClient::VoipClient () {
NS_LOG_FUNCTION (this);
}
VoipClient::~VoipClient () {
NS_LOG_FUNCTION (this);
}
void VoipClient::StartApplication () {
NS_LOG_FUNCTION (this);
if (m_socket == 0) {
m_socket = Socket::CreateSocket (GetNode (), UdpSocketFactory::GetTypeId ());
m_socket->Connect (m_peer);
m_socket->SetRecvCallback (MakeCallback (&VoipClient::HandleRead, this));
m_sendEvent = Simulator::Schedule (Seconds (1.0), &VoipClient::SendRequest, this);
}
}
void VoipClient::StopApplication () {
NS_LOG_FUNCTION (this);
if (m_socket) {
m_socket->Close ();
}
Simulator::Cancel (m_sendEvent);
}
void VoipClient::SendRequest () {
NS_LOG_FUNCTION (this);
std::string request = “REQUEST RTP STREAM\r\n”;
Ptr<Packet> packet = Create<Packet> ((const uint8_t *)request.c_str (), request.size ());
m_socket->Send (packet);
NS_LOG_INFO (“Sent request to server: ” << request);
}
void VoipClient::HandleRead (Ptr<Socket> socket) {
NS_LOG_FUNCTION (this << socket);
Ptr<Packet> packet;
Address from;
while ((packet = socket->RecvFrom (from))) {
uint8_t *buffer = new uint8_t[packet->GetSize ()];
packet->CopyData (buffer, packet->GetSize ());
std::string response = std::string ((char *)buffer, packet->GetSize ());
NS_LOG_INFO (“Received response from server: ” << response);
delete[] buffer;
}
}
} // namespace ns3
- Create VoIP helper class
To facilitate the use and to test VoIP, create helper classes.
voip-helper.h
#ifndef VOIP_HELPER_H
#define VOIP_HELPER_H
#include “ns3/application-container.h”
#include “ns3/node-container.h”
#include “ns3/voip-server.h”
#include “ns3/voip-client.h”
namespace ns3 {
class VoipServerHelper {
public:
VoipServerHelper (Address address);
ApplicationContainer Install (NodeContainer c);
private:
Ptr<Application> InstallPriv (Ptr<Node> node);
Address m_address;
};
class VoipClientHelper {
public:
VoipClientHelper (Address address);
ApplicationContainer Install (NodeContainer c);
private:
Ptr<Application> InstallPriv (Ptr<Node> node);
Address m_address;
};
} // namespace ns3
#endif // VOIP_HELPER_H
voip-helper.cc
#include “voip-helper.h”
#include “ns3/uinteger.h”
#include “ns3/names.h”
namespace ns3 {
VoipServerHelper::VoipServerHelper (Address address)
: m_address (address) {
}
ApplicationContainer VoipServerHelper::Install (NodeContainer c) {
ApplicationContainer apps;
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) {
Ptr<Node> node = *i;
Ptr<Application> app = InstallPriv (node);
apps.Add (app);
}
return apps;
}
Ptr<Application> VoipServerHelper::InstallPriv (Ptr<Node> node) {
Ptr<VoipServer> server = CreateObject<VoipServer> ();
server->SetAttribute (“Local”, AddressValue (m_address));
node->AddApplication (server);
return server;
}
VoipClientHelper::VoipClientHelper (Address address)
: m_address (address) {
}
ApplicationContainer VoipClientHelper::Install (NodeContainer c) {
ApplicationContainer apps;
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) {
Ptr<Node> node = *i;
Ptr<Application> app = InstallPriv (node);
apps.Add (app);
}
return apps;
}
Ptr<Application> VoipClientHelper::InstallPriv (Ptr<Node> node) {
Ptr<VoipClient> client = CreateObject<VoipClient> ();
client->SetAttribute (“Remote”, AddressValue (m_address));
node->AddApplication (client);
return client;
}
} // namespace ns3
- Integrate VoIP with ns3 build system
To include your new VoIP module, update the wscript file in the src directory.
src/voip/wscript
def build(bld):
module = bld.create_ns3_module(‘voip’, [‘core’, ‘network’, ‘internet’, ‘applications’])
module.source = [
‘model/voip-server.cc’,
‘model/voip-client.cc’,
‘helper/voip-helper.cc’,
]
headers = bld(features=’ns3header’)
headers.module = ‘voip’
headers.source = [
‘model/voip-server.h’,
‘model/voip-client.h’,
‘helper/voip-helper.h’,
]
- Build and test
Rebuild ns3 to include your new VoIP module.
./waf configure
./waf build
Create test scripts to verify the implementation of your VoIP protocol.
scratch/test-voip.cc
#include “ns3/core-module.h”
#include “ns3/network-module.h”
#include “ns3/internet-module.h”
#include “ns3/point-to-point-module.h”
#include “ns3/voip-helper.h”
using namespace ns3;
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
NodeContainer nodes;
nodes.Create (2);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute (“DataRate”, StringValue (“5Mbps”));
pointToPoint.SetChannelAttribute (“Delay”, StringValue (“2ms”));
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes);
InternetStackHelper stack;
stack.Install (nodes);
Ipv4AddressHelper address;
address.SetBase (“10.1.1.0”, “255.255.255.0”);
Ipv4InterfaceContainer interfaces = address.Assign (devices);
VoipServerHelper voipServer (InetSocketAddress (Ipv4Address::GetAny (), 5004));
ApplicationContainer serverApps = voipServer.Install (nodes.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
VoipClientHelper voipClient (InetSocketAddress (interfaces.GetAddress (1), 5004));
ApplicationContainer clientApps = voipClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
- Run and debug
Run your test script and debug any issues that arise.
./waf –run scratch/test-voip
Overall, we had successfully executed the Voice over IP (VoIP) in ns3 by applications for simulating VoIP traffic, such as a VoIP client and server. More programming support on VoIP (Voice over IP) are assisted by ms3simulation.com.