To implement MPLS (Multiprotocol Label Switching) in ns3, we need to create a custom module as ns3 does not natively support MPLS. But you can incorporate the behaviour of MPLS by simulating label switching that manipulates packet. Here are the steps to implement a basic MPLS-like functionality in ns3.
Steps for implementing MPLS 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 ns3 script
On your ns3 installation, create a new simulation script in the scratch directory. For example, create a file named mpls-simulation.cc.
cd ns-3.xx
cd scratch
touch mpls-simulation.cc
- Include necessary headers
Include the necessary headers on the mpls-simulation.cc for your simulation.
#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/mpls-module.h”
using namespace ns3;
- Create MPLS header
To attach labels to packets, create a custom MPLS header. Create a new directory named mpls in the src directory and then create the header file mpls-header.h.
#ifndef MPLS_HEADER_H
#define MPLS_HEADER_H
#include “ns3/header.h”
namespace ns3 {
class MplsHeader : public Header
{
public:
MplsHeader ();
virtual ~MplsHeader ();
void SetLabel (uint32_t label);
uint32_t GetLabel () const;
static TypeId GetTypeId (void);
virtual TypeId GetInstanceTypeId () const;
virtual void Print (std::ostream &os) const;
virtual void Serialize (Buffer::Iterator start) const;
virtual uint32_t Deserialize (Buffer::Iterator start);
virtual uint32_t GetSerializedSize () const;
private:
uint32_t m_label;
};
} // namespace ns3
#endif /* MPLS_HEADER_H */
Create the source file mpls-header.cc in the same directory.
#include “mpls-header.h”
#include “ns3/address-utils.h”
#include “ns3/packet.h”
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (MplsHeader);
MplsHeader::MplsHeader ()
: m_label (0)
{
}
MplsHeader::~MplsHeader ()
{
}
TypeId
MplsHeader::GetTypeId (void)
{
static TypeId tid = TypeId (“ns3::MplsHeader”)
.SetParent<Header> ()
.SetGroupName(“Mpls”)
.AddConstructor<MplsHeader> ();
return tid;
}
TypeId
MplsHeader::GetInstanceTypeId () const
{
return GetTypeId ();
}
void
MplsHeader::SetLabel (uint32_t label)
{
m_label = label;
}
uint32_t
MplsHeader::GetLabel () const
{
return m_label;
}
void
MplsHeader::Print (std::ostream &os) const
{
os << “Label: ” << m_label;
}
void
MplsHeader::Serialize (Buffer::Iterator start) const
{
start.WriteHtonU32 (m_label);
}
uint32_t
MplsHeader::Deserialize (Buffer::Iterator start)
{
m_label = start.ReadNtohU32 ();
return GetSerializedSize ();
}
uint32_t
MplsHeader::GetSerializedSize () const
{
return 4; // 4 bytes for the label
}
} // namespace ns3
- Define MPLS Forwarding
In the mpls directory, create the MPLS forwarding logic. Create the header file mpls-forwarding.h.
#ifndef MPLS_FORWARDING_H
#define MPLS_FORWARDING_H
#include “ns3/ipv4-routing-protocol.h”
#include “ns3/ipv4-address.h”
#include “ns3/node.h”
#include “ns3/net-device.h”
#include “ns3/ipv4-header.h”
#include “ns3/ipv4-routing-table-entry.h”
#include “mpls-header.h”
namespace ns3 {
class MplsForwarding : public Ipv4RoutingProtocol
{
public:
static TypeId GetTypeId (void);
MplsForwarding ();
virtual ~MplsForwarding ();
void AddRoute (uint32_t label, Ipv4Address nextHop, uint32_t interface);
virtual Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr);
virtual bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb);
virtual void NotifyInterfaceUp (uint32_t interface);
virtual void NotifyInterfaceDown (uint32_t interface);
virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void SetIpv4 (Ptr<Ipv4> ipv4);
private:
Ptr<Ipv4> m_ipv4;
std::map<uint32_t, Ipv4RoutingTableEntry> m_forwardingTable;
void PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const;
};
} // namespace ns3
#endif /* MPLS_FORWARDING_H */
Create the source file mpls-forwarding.cc in the same directory.
#include “mpls-forwarding.h”
#include “ns3/log.h”
#include “ns3/ipv4-route.h”
#include “ns3/simulator.h”
namespace ns3 {
NS_LOG_COMPONENT_DEFINE (“MplsForwarding”);
NS_OBJECT_ENSURE_REGISTERED (MplsForwarding);
TypeId
MplsForwarding::GetTypeId (void)
{
static TypeId tid = TypeId (“ns3::MplsForwarding”)
.SetParent<Ipv4RoutingProtocol> ()
.SetGroupName(“Mpls”)
.AddConstructor<MplsForwarding> ();
return tid;
}
MplsForwarding::MplsForwarding ()
{
}
MplsForwarding::~MplsForwarding ()
{
}
void
MplsForwarding::SetIpv4 (Ptr<Ipv4> ipv4)
{
m_ipv4 = ipv4;
}
void
MplsForwarding::AddRoute (uint32_t label, Ipv4Address nextHop, uint32_t interface)
{
Ipv4RoutingTableEntry entry (Ipv4Address (), Ipv4Mask (), nextHop, interface);
m_forwardingTable[label] = entry;
}
Ptr<Ipv4Route>
MplsForwarding::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
{
// For simplicity, just pass the packet to the next hop based on the label
MplsHeader mplsHeader;
p->PeekHeader (mplsHeader);
uint32_t label = mplsHeader.GetLabel ();
auto it = m_forwardingTable.find (label);
if (it != m_forwardingTable.end ())
{
Ipv4RoutingTableEntry entry = it->second;
Ptr<Ipv4Route> route = Create<Ipv4Route> ();
route->SetDestination (header.GetDestination ());
route->SetGateway (entry.GetGateway ());
route->SetOutputDevice (m_ipv4->GetNetDevice (entry.GetInterface ()));
return route;
}
sockerr = Socket::ERROR_NOROUTETOHOST;
return nullptr;
}
bool
MplsForwarding::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
{
// Handle the incoming packet with MPLS label
MplsHeader mplsHeader;
p->PeekHeader (mplsHeader);
uint32_t label = mplsHeader.GetLabel ();
auto it = m_forwardingTable.find (label);
if (it != m_forwardingTable.end ())
{
Ipv4RoutingTableEntry entry = it->second;
Ptr<Ipv4Route> route = Create<Ipv4Route> ();
route->SetDestination (header.GetDestination ());
route->SetGateway (entry.GetGateway ());
route->SetOutputDevice (m_ipv4->GetNetDevice (entry.GetInterface ()));
ucb (route, p, header);
return true;
}
ecb (p, header, Socket::ERROR_NOROUTETOHOST);
return false;
}
void
MplsForwarding::NotifyInterfaceUp (uint32_t interface)
{
}
void
MplsForwarding::NotifyInterfaceDown (uint32_t interface)
{
}
void
MplsForwarding::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
{
}
void
MplsForwarding::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
{
}
void
MplsForwarding::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
{
*stream->GetStream () << “MPLS Forwarding Table” << std::endl;
for (auto it = m_forwardingTable.begin (); it != m_forwardingTable.end (); ++it)
{
*stream->GetStream () << “Label: ” << it->first << ” -> ” << it->second.GetGateway () << ” via ” << it->second.GetInterface () << std::endl;
}
}
} // namespace ns3
- Integrate MPLS Forwarding into ns-3 Simulation
Now by using the MPLS forwarding module, create a simulation script. Create the script mpls-simulation.cc in the scratch directory.
#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 “mpls-forwarding.h”
using namespace ns3;
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
NodeContainer nodes;
nodes.Create (4);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute (“DataRate”, StringValue (“5Mbps”));
pointToPoint.SetChannelAttribute (“Delay”, StringValue (“2ms”));
NetDeviceContainer devices;
devices = pointToPoint.Install (nodes.Get(0), nodes.Get(1));
devices.Add (pointToPoint.Install (nodes.Get(1), nodes.Get(2)));
devices.Add (pointToPoint.Install (nodes.Get(2), nodes.Get(3)));
InternetStackHelper stack;
stack.Install (nodes);
Ipv4AddressHelper address;
address.SetBase (“10.1.1.0”, “255.255.255.0”);
Ipv4InterfaceContainer interfaces = address.Assign (devices);
Ptr<MplsForwarding> mpls1 = CreateObject<MplsForwarding> ();
Ptr<MplsForwarding> mpls2 = CreateObject<MplsForwarding> ();
mpls1->AddRoute (1, Ipv4Address (“10.1.1.2”), 1);
mpls1->AddRoute (2, Ipv4Address (“10.1.1.2”), 2);
mpls2->AddRoute (1, Ipv4Address (“10.1.1.3”), 1);
mpls2->AddRoute (2, Ipv4Address (“10.1.1.3”), 2);
nodes.Get (1)->AggregateObject (mpls1);
nodes.Get (2)->AggregateObject (mpls2);
// Set up applications (e.g., a UDP echo server and client)
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (nodes.Get (3));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (interfaces.GetAddress (3), 9);
echoClient.SetAttribute (“MaxPackets”, UintegerValue (1));
echoClient.SetAttribute (“Interval”, TimeValue (Seconds (1.0)));
echoClient.SetAttribute (“PacketSize”, UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (nodes.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
// Enable tracing
AsciiTraceHelper ascii;
pointToPoint.EnableAsciiAll (ascii.CreateFileStream (“mpls-simulation.tr”));
pointToPoint.EnablePcapAll (“mpls-simulation”);
// Run the simulation
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
- Update CMakeList.txt
In the ns3 build system, add a new MPLS module. Edit src/CMakeLists.txt and add the following line:
add_subdirectory (mpls)
Create src/mpls/CMakeLists.txt with the following content:
ns3_add_library (mpls
model/mpls-header.cc
model/mpls-forwarding.cc
)
target_link_libraries (mpls)
- Build and run the simulation
Build and run your script after writing.
./waf build
./waf –run scratch/mpls-simulation
Overall, we had successfully analyzed our implementation results which incorporates the behavior of MPLS by manipulating packets and routing in a way that simulates label switching.
Also, we offer more related information on MPLS protocol. We work on all projects related to MPLS protocol in ns3