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

How to Implement Data Link Layer in ns3

To implement a custom Data link layer (DLL) in ns3, this makes new classes that execute the characteristics of DLL that contains framing, error classification and medium access control. Here are the steps on how to implement the custom data link layer in ns3:

Steps to Implement a Custom Data Link Layer in ns3

  1. Set Up Your ns3 Workspace: Make certain ns3 is installed in the computer and configure with working directory.
  2. Create a New Module for the Data Link Layer:
    • Navigate to the src directory of ns3 and create a new directory named custom-dll.
    • Inside the custom-dll directory, create subdirectories: model, helper, and examples.
  3. Define the Data Link Layer Classes:
    • In the model directory, create .cc and .h files for the data link layer. Define the classes that simulate the behavior of the data link layer, such as CustomMac, CustomChannel, and CustomNetDevice.
  4. Implement the Data Link Layer Classes:
    • The key components of data link layer are framing, classifying the error, and the medium access control.
    • Generate classes for the data link channel and network device that communicate with the data link layer.
  5. Integrate the Data Link Layer with ns3 Network System:
    • Modify the NetDevice class or create a custom network device that can handle the data link layer logic.
    • Register the custom data link layer as a protocol in ns3.
  6. Create a Simulation Script:
    • Set up a network topology.
    • Download the Internet stack.
    • Use the custom data link layer helper to enable the data link layer.
    • Configure applications and execute the simulation.

Example Code Structure

The given below is the sample snippet to implement the custom data link layer in ns3:

  1. Define Custom Data Link Layer Classes

// src/custom-dll/model/custom-mac.h

#ifndef CUSTOM_MAC_H

#define CUSTOM_MAC_H

#include “ns3/object.h”

#include “ns3/net-device.h”

#include “ns3/packet.h”

#include “ns3/nstime.h”

namespace ns3 {

class CustomChannel;

class CustomMac : public Object

{

public:

static TypeId GetTypeId (void);

CustomMac ();

virtual ~CustomMac ();

void SetChannel (Ptr<CustomChannel> channel);

void SendPacket (Ptr<Packet> packet);

void ReceivePacket (Ptr<Packet> packet);

private:

void TransmitPacket ();

Ptr<CustomChannel> m_channel;

Ptr<Packet> m_txPacket;

Time m_txDuration;

};

} // namespace ns3

#endif // CUSTOM_MAC_H

2.     Implement Custom Data Link Layer Classes

// src/custom-dll/model/custom-mac.cc

#include “custom-mac.h”

#include “custom-channel.h”

#include “ns3/log.h”

#include “ns3/simulator.h”

namespace ns3 {

NS_LOG_COMPONENT_DEFINE (“CustomMac”);

NS_OBJECT_ENSURE_REGISTERED (CustomMac);

TypeId

CustomMac::GetTypeId (void)

{

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

.SetParent<Object> ()

.SetGroupName (“Network”)

.AddConstructor<CustomMac> ();

return tid;

}

CustomMac::CustomMac ()

{

NS_LOG_FUNCTION (this);

}

CustomMac::~CustomMac ()

{

NS_LOG_FUNCTION (this);

}

void

CustomMac::SetChannel (Ptr<CustomChannel> channel)

{

NS_LOG_FUNCTION (this << channel);

m_channel = channel;

}

void

CustomMac::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, &CustomMac::TransmitPacket, this);

}

void

CustomMac::TransmitPacket ()

{

NS_LOG_FUNCTION (this);

if (m_channel)

{

m_channel->Transmit (m_txPacket, this);

}

}

void

CustomMac::ReceivePacket (Ptr<Packet> packet)

{

NS_LOG_FUNCTION (this << packet);

// Process received packet (e.g., framing, error detection)

}

} // namespace ns3

3.     Define Custom Channel

// src/custom-dll/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-mac.h”

namespace ns3 {

class CustomChannel : public Object

{

public:

static TypeId GetTypeId (void);

CustomChannel ();

virtual ~CustomChannel ();

void AddDevice (Ptr<NetDevice> device, Ptr<CustomMac> mac);

void Transmit (Ptr<Packet> packet, Ptr<CustomMac> sender);

private:

struct DeviceEntry

{

Ptr<NetDevice> device;

Ptr<CustomMac> mac;

};

std::vector<DeviceEntry> m_devices;

};

} // namespace ns3

#endif // CUSTOM_CHANNEL_H

 

4.     Implement Custom Channel

// src/custom-dll/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<CustomMac> mac)

{

NS_LOG_FUNCTION (this << device << mac);

DeviceEntry entry = {device, mac};

m_devices.push_back (entry);

}

void

CustomChannel::Transmit (Ptr<Packet> packet, Ptr<CustomMac> sender)

{

NS_LOG_FUNCTION (this << packet << sender);

// Simulate propagation delay and attenuation

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

for (auto &entry : m_devices)

{

if (entry.mac != sender)

{

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

delay, &CustomMac::ReceivePacket,

entry.mac, packet->Copy ());

}

}

}

} // namespace ns3

Define Custom Net Device

// src/custom-dll/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-mac.h”

namespace ns3 {

class CustomNetDevice : public NetDevice

{

public:

static TypeId GetTypeId (void);

CustomNetDevice ();

virtual ~CustomNetDevice ();

void SetMac (Ptr<CustomMac> mac);

// 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<CustomMac> m_mac;

Ptr<Node> m_node;

Mac48Address m_address;

NetDevice::ReceiveCallback m_rxCallback;

};

} // namespace ns3

#endif // CUSTOM_NET_DEVICE_H

5.     Implement Custom Net Device

// src/custom-dll/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::SetMac (Ptr<CustomMac> mac)

{

NS_LOG_FUNCTION (this << mac);

m_mac = mac;

}

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_mac->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_mac->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

6.     Define Custom Helper

// src/custom-dll/helper/custom-dll-helper.h

#ifndef CUSTOM_DLL_HELPER_H

#define CUSTOM_DLL_HELPER_H

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

#include “ns3/object-factory.h”

#include “ns3/custom-mac.h”

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

#include “ns3/custom-channel.h”

namespace ns3 {

class CustomDllHelper

{

public:

CustomDllHelper ();

void Install (NodeContainer c) const;

void Install (Ptr<Node> node) const;

void Install (Ptr<NetDevice> device) const;

private:

ObjectFactory m_macFactory;

ObjectFactory m_deviceFactory;

ObjectFactory m_channelFactory;

};

} // namespace ns3

#endif // CUSTOM_DLL_HELPER_H

7.     Implement Custom Helper

// src/custom-dll/helper/custom-dll-helper.cc

#include “custom-dll-helper.h”

#include “ns3/custom-mac.h”

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

#include “ns3/custom-channel.h”

#include “ns3/node.h”

#include “ns3/ipv4.h”

namespace ns3 {

CustomDllHelper::CustomDllHelper ()

{

m_macFactory.SetTypeId (CustomMac::GetTypeId ());

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

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

}

void

CustomDllHelper::Install (NodeContainer c) const

{

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

{

Install (*i);

}

}

void

CustomDllHelper::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<CustomMac> ());

}

}

void

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

{

Ptr<CustomMac> mac = m_macFactory.Create<CustomMac> ();

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

customDevice->SetMac (mac);

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

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

}

} // namespace ns3

Example Simulation Script

At this direction, we provide the sample script to complete the simulation via ns3:

// examples/custom-dll-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-dll-helper.h”

using namespace ns3;

NS_LOG_COMPONENT_DEFINE (“CustomDllSimulation”);

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 DLL on all nodes

CustomDllHelper customDll;

customDll.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));

Overall, we had implemented the Data link layer that makes new classes and executed by its DLL characteristic in ns3 tool. We also offer and support further performance analysis on  data link layer supports in different tools.