To implement the Spanning Tree Protocol (STP) in ns3, we have to incorporate several steps by creating a simulation which builds a loop-free logical topology for a network. STP is a link layer protocol that check for a loop-free topology for any bridged Ethernet local area network. Below is a complete guide on implementing STP in ns3.
Step-by-step guide on implementing STP in ns3
- Set up your ns3 :
- Make sure that ns3 is installed in the computer. If not, install it.
- Create a New Module for STP:
- Go to the src directory in ns3 and create a new directory named stp. Create subdirectories named model, helper, and examples, inside the src directory.
- Define the STP protocol:
- create .cc and .h files for the STP protocol in the model directory. Define the StpProtocol class that simulates the behavior of STP.
- Implement the STP class:
- Implement the key components of STP such as Bridge Protocol Data Units (BPDU), Root Bridge election, Port Roles (Root Port, Designated Port, and Blocked Port), and the STP state machine. For the BPDU messages and the logic to process these messages, create classes.
- Integrate the STP with ns3 ethernet system:
- Create a custom bridge device or modify the NetDevice class to handle STP logic.
- Create simulation script:
- Set up a network topology.
- Install the Internet stack.
- Use the STP helper to enable STP.
- Set up applications and run the simulation.
Example Code Structure
Below is the example code structure for the implementation of STP in ns3.
Define STP Protocol
// src/stp/model/stp-protocol.h
#ifndef STP_PROTOCOL_H
#define STP_PROTOCOL_H
#include “ns3/packet.h”
#include “ns3/net-device.h”
#include “ns3/timer.h”
#include <vector>
#include <map>
namespace ns3 {
class StpProtocol : public Object
{
public:
static TypeId GetTypeId (void);
StpProtocol ();
virtual ~StpProtocol ();
void Install (Ptr<NetDevice> device);
void ReceiveBpdu (Ptr<Packet> packet, Ptr<NetDevice> device);
private:
void Start ();
void Stop ();
void SendBpdu ();
void HandleBpdu (Ptr<Packet> packet, Ptr<NetDevice> device);
void ElectRootBridge ();
void UpdatePortRoles ();
Ptr<NetDevice> m_device;
Timer m_timer;
bool m_isRootBridge;
uint32_t m_rootBridgeId;
uint32_t m_bridgeId;
std::map<Ptr<NetDevice>, uint32_t> m_portRoles; // Root, Designated, Blocked
};
} // namespace ns3
#endif // STP_PROTOCOL_H
Implement STP Protocol
// src/stp/model/stp-protocol.cc
#include “stp-protocol.h”
#include “ns3/log.h”
#include “ns3/simulator.h”
#include “ns3/packet.h”
namespace ns3 {
NS_LOG_COMPONENT_DEFINE (“StpProtocol”);
NS_OBJECT_ENSURE_REGISTERED (StpProtocol);
TypeId
StpProtocol::GetTypeId (void)
{
static TypeId tid = TypeId (“ns3::StpProtocol”)
.SetParent<Object> ()
.SetGroupName (“Network”)
.AddConstructor<StpProtocol> ();
return tid;
}
StpProtocol::StpProtocol ()
{
NS_LOG_FUNCTION (this);
}
StpProtocol::~StpProtocol ()
{
NS_LOG_FUNCTION (this);
}
void
StpProtocol::Install (Ptr<NetDevice> device)
{
NS_LOG_FUNCTION (this << device);
m_device = device;
m_bridgeId = device->GetNode ()->GetId ();
Start ();
}
void
StpProtocol::Start ()
{
NS_LOG_FUNCTION (this);
m_isRootBridge = true;
m_rootBridgeId = m_bridgeId;
m_timer.SetFunction (&StpProtocol::SendBpdu, this);
m_timer.Schedule (Seconds (2.0));
}
void
StpProtocol::Stop ()
{
NS_LOG_FUNCTION (this);
m_timer.Cancel ();
}
void
StpProtocol::SendBpdu ()
{
NS_LOG_FUNCTION (this);
// Create BPDU packet
Ptr<Packet> packet = Create<Packet> ();
// Add BPDU header information
// …
// Send BPDU on all ports
for (auto it = m_portRoles.begin (); it != m_portRoles.end (); ++it)
{
Ptr<NetDevice> device = it->first;
device->Send (packet, device->GetBroadcast (), 0x0001); // Example protocol number for BPDU
}
m_timer.Schedule (Seconds (2.0));
}
void
StpProtocol::ReceiveBpdu (Ptr<Packet> packet, Ptr<NetDevice> device)
{
NS_LOG_FUNCTION (this << packet << device);
HandleBpdu (packet, device);
}
void
StpProtocol::HandleBpdu (Ptr<Packet> packet, Ptr<NetDevice> device)
{
NS_LOG_FUNCTION (this << packet << device);
// Process BPDU packet
// …
ElectRootBridge ();
UpdatePortRoles ();
}
void
StpProtocol::ElectRootBridge ()
{
NS_LOG_FUNCTION (this);
// Elect root bridge based on received BPDU packets
// …
}
void
StpProtocol::UpdatePortRoles ()
{
NS_LOG_FUNCTION (this);
// Update port roles (Root, Designated, Blocked) based on root bridge election
// …
}
} // namespace ns3
Helper Class
// src/stp/helper/stp-helper.h
#ifndef STP_HELPER_H
#define STP_HELPER_H
#include “ns3/net-device-container.h”
#include “ns3/object-factory.h”
#include “ns3/stp-protocol.h”
namespace ns3 {
class StpHelper
{
public:
StpHelper ();
void Install (NodeContainer c) const;
void Install (Ptr<Node> node) const;
void Install (Ptr<NetDevice> device) const;
private:
ObjectFactory m_factory;
};
} // namespace ns3
#endif // STP_HELPER_H
Implement Helper Class
// src/stp/helper/stp-helper.cc
#include “stp-helper.h”
#include “ns3/stp-protocol.h”
#include “ns3/node.h”
#include “ns3/ipv4.h”
namespace ns3 {
StpHelper::StpHelper ()
{
m_factory.SetTypeId (StpProtocol::GetTypeId ());
}
void
StpHelper::Install (NodeContainer c) const
{
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
{
Install (*i);
}
}
void
StpHelper::Install (Ptr<Node> node) const
{
for (uint32_t i = 0; i < node->GetNDevices (); ++i)
{
Ptr<NetDevice> device = node->GetDevice (i);
Install (device);
}
}
void
StpHelper::Install (Ptr<NetDevice> device) const
{
Ptr<StpProtocol> protocol = m_factory.Create<StpProtocol> ();
protocol->Install (device);
}
} // namespace ns3
Example Simulation Script
// examples/stp-simulation.cc
#include “ns3/core-module.h”
#include “ns3/network-module.h”
#include “ns3/internet-module.h”
#include “ns3/bridge-module.h”
#include “ns3/point-to-point-module.h”
#include “ns3/applications-module.h”
#include “ns3/stp-helper.h”
using namespace ns3;
NS_LOG_COMPONENT_DEFINE (“StpSimulation”);
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
// Create nodes
NodeContainer nodes;
nodes.Create (6);
// Create point-to-point links
PointToPointHelper p2p;
p2p.SetDeviceAttribute (“DataRate”, StringValue (“1Gbps”));
p2p.SetChannelAttribute (“Delay”, StringValue (“2ms”));
NetDeviceContainer devices[6][6];
for (int i = 0; i < 6; ++i)
{
for (int j = i + 1; j < 6; ++j)
{
devices[i][j] = p2p.Install (nodes.Get (i), nodes.Get (j));
}
}
// Install STP on all nodes
StpHelper stp;
stp.Install (nodes);
// Install Internet stack
InternetStackHelper internet;
internet.Install (nodes);
// Assign IP addresses
Ipv4AddressHelper address;
for (int i = 0; i < 6; ++i)
{
for (int j = i + 1; j < 6; ++j)
{
std::ostringstream subnet;
subnet << “10.” << i << “.” << j << “.0”;
address.SetBase (subnet.str ().c_str (), “255.255.255.0”);
address.Assign (devices[i][j]);
}
}
// Create a packet sink to receive packets
uint16_t sinkPort = 8080;
Address sinkAddress (InetSocketAddress (Ipv4Address (“10.0.0.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 (“stp-routing.tr”));
p2p.EnablePcapAll (“stp-routing”);
// Run the simulation
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
Running the Simulation
To run the simulation, compile the script and execute it:
./waf configure –enable-examples
./waf build
./waf –run stp-simulation
Overall, we had a performance analysis on the Spanning Tree Protocol (STP) by implementing it in ns3 by creating a simulation that builds a loop-free logical topology for a network. Also, we provide more detailed information on Spanning Tree Protocol (STP) so we assure for best system development.