Ns3 Projects for B.E/B.Tech M.E/M.Tech PhD Scholars.  Phone-Number:9790238391   E-mail: ns3simulation@gmail.com

How to Implement Physical Layer in ns3

To implement a custom physical layer in ns3, we need to understands the concept of ns3 architecture and handling the network layers. For this a new class has to be created to simulate the behavior of the physical layer, including signal transmission, reception, and error handling. Here we have given the steps to guide for implementing the physical layer in ns3.

Steps to Implement a Custom Physical Layer in ns-3

  1. Set Up Your ns-3 Workspace: Make sure ns3 is installed on the system.
  2. Create a New Module for the Physical Layer:
    • Navigate to the src directory of ns-3 and create a new directory named custom-phy.
    • Inside the custom-phy directory, create subdirectories: model, helper, and examples.
  3. Define the Physical Layer Classes:
    • In the model directory, create .cc and .h files for the physical layer. Define the classes that simulate the behavior of the physical layer, such as CustomPhy, CustomChannel, and CustomNetDevice.
  4. Implement the Physical Layer Classes:
    • Implement the key components of the physical layer: signal transmission, signal reception, error handling, and any modulation or coding schemes.
    • Create classes for the physical channel and network device that interact with the physical layer.
  5. Integrate the Physical Layer with ns-3’s Network System:
    • Modify the NetDevice class or create a custom network device that can handle the physical layer logic.
    • Register the custom physical layer as a protocol in ns-3.
  6. Create a Simulation Script:
    • Set up a network topology.
    • Install the Internet stack.
    • Use the custom physical layer helper to enable the physical layer.
    • Set up applications and run the simulation.

Example Code Structure

Here’s an example code structure for implementing a custom physical layer in ns3.

  1. Define Custom Physical Layer Classes

// src/custom-phy/model/custom-phy.h

#ifndef CUSTOM_PHY_H

#define CUSTOM_PHY_H

#include “ns3/object.h”

#include “ns3/net-device.h”

#include “ns3/packet.h”

#include “ns3/nstime.h”

namespace ns3 {

class CustomChannel;

class CustomPhy : public Object

{

public:

static TypeId GetTypeId (void);

CustomPhy ();

virtual ~CustomPhy ();

void SetChannel (Ptr<CustomChannel> channel);

void SendPacket (Ptr<Packet> packet);

void ReceivePacket (Ptr<Packet> packet, double rxPower);

private:

void TransmitPacket ();

 

Ptr<CustomChannel> m_channel;

Ptr<Packet> m_txPacket;

Time m_txDuration;

};

} // namespace ns3

#endif // CUSTOM_PHY_H

2.     Implement Custom Physical Layer Classes

// src/custom-phy/model/custom-phy.cc

#include “custom-phy.h”

#include “custom-channel.h”

#include “ns3/log.h”

#include “ns3/simulator.h”

namespace ns3 {

NS_LOG_COMPONENT_DEFINE (“CustomPhy”);

NS_OBJECT_ENSURE_REGISTERED (CustomPhy);

TypeId

CustomPhy::GetTypeId (void)

{

static TypeId tid = TypeId (“ns3::CustomPhy”)

.SetParent<Object> ()

.SetGroupName (“Network”)

.AddConstructor<CustomPhy> ();

return tid;

}

CustomPhy::CustomPhy ()

{

NS_LOG_FUNCTION (this);

}

CustomPhy::~CustomPhy ()

{

NS_LOG_FUNCTION (this);

}

void

CustomPhy::SetChannel (Ptr<CustomChannel> channel)

{

NS_LOG_FUNCTION (this << channel);

m_channel = channel;

}

void

CustomPhy::SendPacket (Ptr<Packet> packet)

{

NS_LOG_FUNCTION (this << packet);

m_txPacket = packet;

m_txDuration = Seconds (packet->GetSize () * 8 / 1e6); // Example: 1 Mbps data rate

Simulator::Schedule (m_txDuration, &CustomPhy::TransmitPacket, this);

}

 

void

CustomPhy::TransmitPacket ()

{

NS_LOG_FUNCTION (this);

if (m_channel)

{

m_channel->Transmit (m_txPacket, this, 0.0); // Example: 0 dBm transmit power

}

}

void

CustomPhy::ReceivePacket (Ptr<Packet> packet, double rxPower)

{

NS_LOG_FUNCTION (this << packet << rxPower);

// Process received packet (e.g., check for errors based on rxPower)

}

} // namespace ns3

3.     Define Custom Channel

// src/custom-phy/model/custom-channel.h

 

#ifndef CUSTOM_CHANNEL_H

#define CUSTOM_CHANNEL_H

 

#include “ns3/object.h”

#include “ns3/nstime.h”

#include “ns3/traced-callback.h”

#include “ns3/net-device.h”

#include “ns3/custom-phy.h”

namespace ns3 {

class CustomChannel : public Object

{

public:

static TypeId GetTypeId (void);

CustomChannel ();

virtual ~CustomChannel ();

void AddDevice (Ptr<NetDevice> device, Ptr<CustomPhy> phy);

void Transmit (Ptr<Packet> packet, Ptr<CustomPhy> sender, double txPower);

private:

struct DeviceEntry

{

Ptr<NetDevice> device;

Ptr<CustomPhy> phy;

};

std::vector<DeviceEntry> m_devices;

};

 

} // namespace ns3

#endif // CUSTOM_CHANNEL_H

4.     Implement Custom Channel

// src/custom-phy/model/custom-channel.cc

#include “custom-channel.h”

#include “ns3/log.h”

#include “ns3/simulator.h”

namespace ns3 {

NS_LOG_COMPONENT_DEFINE (“CustomChannel”);

NS_OBJECT_ENSURE_REGISTERED (CustomChannel);

TypeId

CustomChannel::GetTypeId (void)

{

static TypeId tid = TypeId (“ns3::CustomChannel”)

.SetParent<Object> ()

.SetGroupName (“Network”)

.AddConstructor<CustomChannel> ();

return tid;

}

CustomChannel::CustomChannel ()

{

NS_LOG_FUNCTION (this);

}

 

CustomChannel::~CustomChannel ()

{

NS_LOG_FUNCTION (this);

}

void

CustomChannel::AddDevice (Ptr<NetDevice> device, Ptr<CustomPhy> phy)

{

NS_LOG_FUNCTION (this << device << phy);

DeviceEntry entry = {device, phy};

m_devices.push_back (entry);

}

void

CustomChannel::Transmit (Ptr<Packet> packet, Ptr<CustomPhy> sender, double txPower)

{

NS_LOG_FUNCTION (this << packet << sender << txPower);

// Simulate propagation delay and attenuation

Time delay = MilliSeconds (1); // Example: fixed delay

for (auto &entry : m_devices)

{

if (entry.phy != sender)

{

Simulator::ScheduleWithContext (entry.device->GetNode ()->GetId (),

delay, &CustomPhy::ReceivePacket,

entry.phy, packet->Copy (), txPower);

}

}

}

} // namespace ns3

5.     Define Custom Net Device

// src/custom-phy/model/custom-net-device.h

#ifndef CUSTOM_NET_DEVICE_H

#define CUSTOM_NET_DEVICE_H

#include “ns3/net-device.h”

#include “ns3/node.h”

#include “ns3/mac48-address.h”

#include “ns3/packet.h”

#include “custom-phy.h”

namespace ns3 {

class CustomNetDevice : public NetDevice

{

public:

static TypeId GetTypeId (void);

CustomNetDevice ();

virtual ~CustomNetDevice ();

 

void SetPhy (Ptr<CustomPhy> phy);

// Inherited from NetDevice

virtual void SetIfIndex (const uint32_t index);

virtual uint32_t GetIfIndex (void) const;

virtual Ptr<Channel> GetChannel (void) const;

virtual void SetAddress (Address address);

virtual Address GetAddress (void) const;

virtual bool SetMtu (const uint16_t mtu);

virtual uint16_t GetMtu (void) const;

virtual bool IsLinkUp (void) const;

virtual void AddLinkChangeCallback (Callback<void> callback);

virtual bool IsBroadcast (void) const;

virtual Address GetBroadcast (void) const;

virtual bool IsMulticast (void) const;

virtual Address GetMulticast (Ipv4Address multicastGroup) const;

virtual bool IsPointToPoint (void) const;

virtual bool IsBridge (void) const;

virtual bool Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber);

virtual bool SendFrom (Ptr<Packet> packet, const Address &source, const Address &dest, uint16_t protocolNumber);

virtual Ptr<Node> GetNode (void) const;

virtual void SetNode (Ptr<Node> node);

virtual bool NeedsArp (void) const;

virtual void SetReceiveCallback (NetDevice::ReceiveCallback cb);

virtual void SetPromiscReceiveCallback (PromiscReceiveCallback cb);

virtual bool SupportsSendFrom (void) const;

private:

Ptr<CustomPhy> m_phy;

Ptr<Node> m_node;

Mac48Address m_address;

NetDevice::ReceiveCallback m_rxCallback;

};

} // namespace ns3

#endif // CUSTOM_NET_DEVICE_H

6.     Implement Custom Net Device

// src/custom-phy/model/custom-net-device.cc

#include “custom-net-device.h”

#include “ns3/log.h”

#include “ns3/packet.h”

#include “ns3/simulator.h”

#include “ns3/node.h”

namespace ns3 {

NS_LOG_COMPONENT_DEFINE (“CustomNetDevice”);

NS_OBJECT_ENSURE_REGISTERED (CustomNetDevice);

TypeId

CustomNetDevice::GetTypeId (void)

{

static TypeId tid = TypeId (“ns3::CustomNetDevice”)

.SetParent<NetDevice> ()

.SetGroupName (“Network”)

.AddConstructor<CustomNetDevice> ();

return tid;

}

CustomNetDevice::CustomNetDevice ()

{

NS_LOG_FUNCTION (this);

}

CustomNetDevice::~CustomNetDevice ()

{

NS_LOG_FUNCTION (this);

}

void

CustomNetDevice::SetPhy (Ptr<CustomPhy> phy)

{

NS_LOG_FUNCTION (this << phy);

m_phy = phy;

}

void

CustomNetDevice::SetIfIndex (const uint32_t index)

{

NS_LOG_FUNCTION (this << index);

}

uint32_t

CustomNetDevice::GetIfIndex (void) const

{

NS_LOG_FUNCTION (this);

return 0;

}

Ptr<Channel>

CustomNetDevice::GetChannel (void) const

{

NS_LOG_FUNCTION (this);

return m_phy->GetObject<Channel> ();

}

void

CustomNetDevice::SetAddress (Address address)

{

NS_LOG_FUNCTION (this << address);

m_address = Mac48Address::ConvertFrom (address);

}

Address

CustomNetDevice::GetAddress (void) const

{

NS_LOG_FUNCTION (this);

return m_address;

}

bool

CustomNetDevice::SetMtu (const uint16_t mtu)

{

NS_LOG_FUNCTION (this << mtu);

return true;

}

uint16_t

CustomNetDevice::GetMtu (void) const

{

NS_LOG_FUNCTION (this);

return 1500;

}

bool

CustomNetDevice::IsLinkUp (void) const

{

NS_LOG_FUNCTION (this);

return true;

}

 

void

CustomNetDevice::AddLinkChangeCallback (Callback<void> callback)

{

NS_LOG_FUNCTION (this << &callback);

}

bool

CustomNetDevice::IsBroadcast (void) const

{

NS_LOG_FUNCTION (this);

return true;

}

Address

CustomNetDevice::GetBroadcast (void) const

{

NS_LOG_FUNCTION (this);

return Mac48Address::GetBroadcast ();

}

bool

CustomNetDevice::IsMulticast (void) const

{

NS_LOG_FUNCTION (this);

return true;

}

 

Address

CustomNetDevice::GetMulticast (Ipv4Address multicastGroup) const

{

NS_LOG_FUNCTION (this << multicastGroup);

return Mac48Address::GetMulticast (multicastGroup);

}

bool

CustomNetDevice::IsPointToPoint (void) const

{

NS_LOG_FUNCTION (this);

return false;

}

bool

CustomNetDevice::IsBridge (void) const

{

NS_LOG_FUNCTION (this);

return false;

}

bool

CustomNetDevice::Send (Ptr<Packet> packet, const Address &dest, uint16_t protocolNumber)

{

NS_LOG_FUNCTION (this << packet << dest << protocolNumber);

m_phy->SendPacket (packet);

return true;

}

bool

CustomNetDevice::SendFrom (Ptr<Packet> packet, const Address &source, const Address &dest, uint16_t protocolNumber)

{

NS_LOG_FUNCTION (this << packet << source << dest << protocolNumber);

return Send (packet, dest, protocolNumber);

}

Ptr<Node>

CustomNetDevice::GetNode (void) const

{

NS_LOG_FUNCTION (this);

return m_node;

}

void

CustomNetDevice::SetNode (Ptr<Node> node)

{

NS_LOG_FUNCTION (this << node);

m_node = node;

}

 

bool

CustomNetDevice::NeedsArp (void) const

{

NS_LOG_FUNCTION (this);

return true;

}

void

CustomNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)

{

NS_LOG_FUNCTION (this << &cb);

m_rxCallback = cb;

}

void

CustomNetDevice::SetPromiscReceiveCallback (PromiscReceiveCallback cb)

{

NS_LOG_FUNCTION (this << &cb);

}

bool

CustomNetDevice::SupportsSendFrom (void) const

{

NS_LOG_FUNCTION (this);

return true;

}

} // namespace ns3

7.     Define Custom Helper

// src/custom-phy/helper/custom-phy-helper.h

#ifndef CUSTOM_PHY_HELPER_H

#define CUSTOM_PHY_HELPER_H

#include “ns3/net-device-container.h”

#include “ns3/object-factory.h”

#include “ns3/custom-phy.h”

#include “ns3/custom-net-device.h”

#include “ns3/custom-channel.h”

namespace ns3 {

class CustomPhyHelper

{

public:

CustomPhyHelper ();

void Install (NodeContainer c) const;

void Install (Ptr<Node> node) const;

void Install (Ptr<NetDevice> device) const;

private:

ObjectFactory m_phyFactory;

ObjectFactory m_deviceFactory;

ObjectFactory m_channelFactory;

};

} // namespace ns3

#endif // CUSTOM_PHY_HELPER_H

8.     Implement Custom Helper

// src/custom-phy/helper/custom-phy-helper.cc

#include “custom-phy-helper.h”

#include “ns3/custom-phy.h”

#include “ns3/custom-net-device.h”

#include “ns3/custom-channel.h”

#include “ns3/node.h”

#include “ns3/ipv4.h”

namespace ns3 {

CustomPhyHelper::CustomPhyHelper ()

{

m_phyFactory.SetTypeId (CustomPhy::GetTypeId ());

m_deviceFactory.SetTypeId (CustomNetDevice::GetTypeId ());

m_channelFactory.SetTypeId (CustomChannel::GetTypeId ());

}

void

CustomPhyHelper::Install (NodeContainer c) const

{

for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)

{

Install (*i);

}

}

void

CustomPhyHelper::Install (Ptr<Node> node) const

{

Ptr<CustomChannel> channel = m_channelFactory.Create<CustomChannel> ();

for (uint32_t i = 0; i < node->GetNDevices (); ++i)

{

Ptr<NetDevice> device = node->GetDevice (i);

Install (device);

Ptr<CustomNetDevice> customDevice = device->GetObject<CustomNetDevice> ();

customDevice->SetChannel (channel);

channel->AddDevice (device, customDevice->GetObject<CustomPhy> ());

}

}

void

CustomPhyHelper::Install (Ptr<NetDevice> device) const

{

Ptr<CustomPhy> phy = m_phyFactory.Create<CustomPhy> ();

Ptr<CustomNetDevice> customDevice = m_deviceFactory.Create<CustomNetDevice> ();

customDevice->SetPhy (phy);

device->GetNode ()->AddDevice (customDevice);

phy->SetChannel (device->GetObject<CustomChannel> ());

}

} // namespace ns3

Example Simulation Script

// examples/custom-phy-simulation.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/applications-module.h”

#include “ns3/custom-phy-helper.h”

using namespace ns3;

NS_LOG_COMPONENT_DEFINE (“CustomPhySimulation”);

int main (int argc, char *argv[])

{

CommandLine cmd;

cmd.Parse (argc, argv);

// Create nodes

NodeContainer nodes;

nodes.Create (4);

// Create point-to-point links

PointToPointHelper p2p;

p2p.SetDeviceAttribute (“DataRate”, StringValue (“1Gbps”));

p2p.SetChannelAttribute (“Delay”, StringValue (“2ms”));

NetDeviceContainer devices01 = p2p.Install (nodes.Get (0), nodes.Get (1));

NetDeviceContainer devices12 = p2p.Install (nodes.Get (1), nodes.Get (2));

NetDeviceContainer devices23 = p2p.Install (nodes.Get (2), nodes.Get (3));

NetDeviceContainer devices30 = p2p.Install (nodes.Get (3), nodes.Get (0));

// Install Custom PHY on all nodes

CustomPhyHelper customPhy;

customPhy.Install (nodes);

// Install Internet stack

InternetStackHelper internet;

internet.Install (nodes);

// Assign IP addresses

Ipv4AddressHelper address;

address.SetBase (“10.1.1.0”, “255.255.255.0”);

Ipv4InterfaceContainer interfaces01 = address.Assign (devices01);

address.SetBase (“10.1.2.0”, “255.255.255.0”);

Ipv4InterfaceContainer interfaces12 = address.Assign (devices12);

address.SetBase (“10.1.3.0”, “255.255.255.0”);

Ipv4InterfaceContainer interfaces23 = address.Assign (devices23);

address.SetBase (“10.1.4.0”, “255.255.255.0”);

Ipv4InterfaceContainer interfaces30 = address.Assign (devices30);

// Create a packet sink to receive packets

uint16_t sinkPort = 8080;

Address sinkAddress (InetSocketAddress (Ipv4Address (“10.1.1.1”), sinkPort));

PacketSinkHelper packetSinkHelper (“ns3::TcpSocketFactory”, sinkAddress);

ApplicationContainer sinkApps = packetSinkHelper.Install (nodes.Get (0));

sinkApps.Start (Seconds (1.0));

sinkApps.Stop (Seconds (10.0));

// Create a TCP client to send packets

OnOffHelper clientHelper (“ns3::TcpSocketFactory”, sinkAddress);

clientHelper.SetAttribute (“OnTime”, StringValue (“ns3::ConstantRandomVariable[Constant=1]”));

clientHelper.SetAttribute (“OffTime”, StringValue (“ns3::ConstantRandomVariable[Constant=0]”));

clientHelper.SetAttribute (“DataRate”, DataRateValue (DataRate (“1Mbps”)));

clientHelper.SetAttribute (“PacketSize”, UintegerValue (1024));

ApplicationContainer clientApps = clientHelper.Install (nodes.Get (1));

clientApps.Start (Seconds (2.0));

clientApps.Stop (Seconds (10.0));

// Enable tracing

AsciiTraceHelper ascii;

p2p.EnableAsciiAll (ascii.CreateFileStream (“custom-phy.tr”));

p2p.EnablePcapAll (“custom-phy”);

// Run the simulation

Simulator::Run ();

Simulator::Destroy ();

 

return 0;

}

9.     Running the Simulation

To run the simulation, compile the script and execute it:

./waf configure –enable-examples

./waf build

./waf –run custom-phy-simulation

From this, steps given above has explained detailly about the implementation process of physical layer in ns3 by creating a new custom module for physical layer to implement and simulate the script in network topology. We create network topology based on custom physical layer in ns3 with programming aid.