Update README and add contrib dir
This commit is contained in:
209
contrib/tsn/examples/tsn-switched-withGPTP.cc
Normal file
209
contrib/tsn/examples/tsn-switched-withGPTP.cc
Normal file
@@ -0,0 +1,209 @@
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/applications-module.h"
|
||||
#include "ns3/command-line.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
|
||||
#include "ns3/tsn-node.h"
|
||||
#include "ns3/tsn-net-device.h"
|
||||
#include "ns3/switch-net-device.h"
|
||||
#include "ns3/ethernet-channel.h"
|
||||
#include "ns3/clock.h"
|
||||
#include "ns3/clock-constant-drift.h"
|
||||
#include "ns3/gPTP.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Example of the use of gPTP on a network composed of three end-stations
|
||||
* and connected by a 1Gb/s full duplex network through a switch. ES1 is the
|
||||
* GPTP Grandmaster.
|
||||
* ES1 === SW1 === ES3
|
||||
* ||
|
||||
* ES2
|
||||
*/
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE("Example");
|
||||
|
||||
static void
|
||||
PdelayCallback(std::string context, Ptr<TsnNetDevice> net, double pdelay)
|
||||
{
|
||||
NS_LOG_INFO("[GPTP] At " << Simulator::Now() << " on "<< context << "/" << Names::FindName(net) << " computed pdelay = " << pdelay);
|
||||
}
|
||||
|
||||
static void
|
||||
ClockAfterCorrectionCallback(std::string context, Ptr<Clock> gmClock, Time clockValue)
|
||||
{
|
||||
NS_LOG_INFO("[GPTP] At " << Simulator::Now() << " on "<< context << " clock value after correction = " << clockValue.GetNanoSeconds() << "ns (error = "<< (gmClock->GetLocalTime()-clockValue).GetNanoSeconds() << "ns)");
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[])
|
||||
{
|
||||
//Enable logging
|
||||
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||||
LogComponentEnable("TsnNode", LOG_LEVEL_INFO);
|
||||
|
||||
CommandLine cmd(__FILE__);
|
||||
cmd.Parse(argc, argv);
|
||||
|
||||
//Create nodes
|
||||
Ptr<TsnNode> n0 = CreateObject<TsnNode>();
|
||||
Names::Add("ES1", n0);
|
||||
Ptr<TsnNode> n1 = CreateObject<TsnNode>();
|
||||
Names::Add("ES2", n1);
|
||||
Ptr<TsnNode> n2 = CreateObject<TsnNode>();
|
||||
Names::Add("ES3", n2);
|
||||
Ptr<TsnNode> n3 = CreateObject<TsnNode>();
|
||||
Names::Add("SW1", n3);
|
||||
|
||||
|
||||
//Create and add clock to TsnNode
|
||||
Ptr<ConstantDriftClock> c0 = CreateObject<ConstantDriftClock>();
|
||||
c0->SetAttribute("InitialOffset", TimeValue(Seconds(112)));
|
||||
c0->SetAttribute("DriftRate", DoubleValue(-15));
|
||||
c0->SetAttribute("Granularity", TimeValue(NanoSeconds(10)));
|
||||
n0->SetMainClock(c0);
|
||||
|
||||
Ptr<ConstantDriftClock> c1 = CreateObject<ConstantDriftClock>();
|
||||
c1->SetAttribute("InitialOffset", TimeValue(Seconds(3)));
|
||||
c1->SetAttribute("DriftRate", DoubleValue(10));
|
||||
c1->SetAttribute("Granularity", TimeValue(NanoSeconds(10)));
|
||||
n1->SetMainClock(c1);
|
||||
|
||||
Ptr<ConstantDriftClock> c2 = CreateObject<ConstantDriftClock>();
|
||||
c2->SetAttribute("InitialOffset", TimeValue(Seconds(1.5)));
|
||||
c2->SetAttribute("DriftRate", DoubleValue(-8));
|
||||
c2->SetAttribute("Granularity", TimeValue(NanoSeconds(10)));
|
||||
n2->SetMainClock(c2);
|
||||
|
||||
Ptr<ConstantDriftClock> c3 = CreateObject<ConstantDriftClock>();
|
||||
c3->SetAttribute("InitialOffset", TimeValue(Seconds(5)));
|
||||
c3->SetAttribute("DriftRate", DoubleValue(-5));
|
||||
c3->SetAttribute("Granularity", TimeValue(NanoSeconds(10)));
|
||||
n3->SetMainClock(c3);
|
||||
|
||||
|
||||
//Create and add a netDevice to each node
|
||||
Ptr<TsnNetDevice> net0 = CreateObject<TsnNetDevice>();
|
||||
net0->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n0->AddDevice(net0);
|
||||
Names::Add("ES1#01", net0);
|
||||
Ptr<TsnNetDevice> net1 = CreateObject<TsnNetDevice>();
|
||||
net1->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n1->AddDevice(net1);
|
||||
Names::Add("ES2#01", net1);
|
||||
Ptr<TsnNetDevice> net2 = CreateObject<TsnNetDevice>();
|
||||
net2->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n2->AddDevice(net2);
|
||||
Names::Add("ES3#01", net2);
|
||||
|
||||
Ptr<TsnNetDevice> net3_0 = CreateObject<TsnNetDevice>();
|
||||
net3_0->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n3->AddDevice(net3_0);
|
||||
Names::Add("SW1#01", net3_0);
|
||||
Ptr<TsnNetDevice> net3_1 = CreateObject<TsnNetDevice>();
|
||||
net3_1->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n3->AddDevice(net3_1);
|
||||
Names::Add("SW1#02", net3_1);
|
||||
Ptr<TsnNetDevice> net3_2 = CreateObject<TsnNetDevice>();
|
||||
net3_2->SetAttribute("DataRate", DataRateValue(DataRate("1Gb/s")));
|
||||
n3->AddDevice(net3_2);
|
||||
Names::Add("SW1#03", net3_2);
|
||||
|
||||
//Create and add a switch net device to the switch node
|
||||
Ptr<SwitchNetDevice> sw = CreateObject<SwitchNetDevice>();
|
||||
sw->SetAttribute("MinForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
sw->SetAttribute("MaxForwardingLatency", TimeValue(MicroSeconds(10)));
|
||||
n3->AddDevice(sw);
|
||||
sw->AddSwitchPort(net3_0);
|
||||
sw->AddSwitchPort(net3_1);
|
||||
sw->AddSwitchPort(net3_2);
|
||||
|
||||
//Create Ethernet Channel and attach it two the netDevices
|
||||
Ptr<EthernetChannel> l0 = CreateObject<EthernetChannel>();
|
||||
l0->SetAttribute("Delay", TimeValue(Time(NanoSeconds(200))));
|
||||
net0->Attach(l0);
|
||||
net3_0->Attach(l0);
|
||||
Ptr<EthernetChannel> l1 = CreateObject<EthernetChannel>();
|
||||
l1->SetAttribute("Delay", TimeValue(Time(NanoSeconds(200))));
|
||||
net1->Attach(l1);
|
||||
net3_1->Attach(l1);
|
||||
Ptr<EthernetChannel> l2 = CreateObject<EthernetChannel>();
|
||||
l2->SetAttribute("Delay", TimeValue(Time(NanoSeconds(200))));
|
||||
net2->Attach(l2);
|
||||
net3_2->Attach(l2);
|
||||
|
||||
//Allocate a Mac address
|
||||
net0->SetAddress(Mac48Address::Allocate());
|
||||
net1->SetAddress(Mac48Address::Allocate());
|
||||
net2->SetAddress(Mac48Address::Allocate());
|
||||
sw->SetAddress(Mac48Address::Allocate());
|
||||
net3_0->SetAddress(Mac48Address::Allocate());
|
||||
net3_1->SetAddress(Mac48Address::Allocate());
|
||||
net3_2->SetAddress(Mac48Address::Allocate());
|
||||
|
||||
//Add one fifo per netdevice.
|
||||
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net3_0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net3_1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
net3_2->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||||
|
||||
//Add and configure GPTP
|
||||
Ptr<GPTP> gPTP0 = CreateObject<GPTP>();
|
||||
gPTP0->SetNode(n0);
|
||||
gPTP0->SetMainClock(c0);
|
||||
gPTP0->AddDomain(0);
|
||||
gPTP0->AddPort(net0, GPTP::MASTER, 0);
|
||||
gPTP0->SetAttribute("SyncInterval", TimeValue(Seconds(0.125))); //This line is not mandatory because 0.125s is the default value
|
||||
gPTP0->SetAttribute("PdelayInterval", TimeValue(Seconds(1))); //This line is not mandatory because 1s is the default value
|
||||
gPTP0->SetAttribute("Priority", UintegerValue(0));
|
||||
n0->AddApplication(gPTP0);
|
||||
gPTP0->SetStartTime(Seconds(0));
|
||||
|
||||
Ptr<GPTP> gPTP1 = CreateObject<GPTP>();
|
||||
gPTP1->SetNode(n1);
|
||||
gPTP1->SetMainClock(c1);
|
||||
gPTP1->AddDomain(0);
|
||||
gPTP1->AddPort(net1, GPTP::SLAVE, 0);
|
||||
gPTP1->SetAttribute("Priority", UintegerValue(0));
|
||||
n1->AddApplication(gPTP1);
|
||||
gPTP1->SetStartTime(Seconds(0));
|
||||
|
||||
Ptr<GPTP> gPTP2 = CreateObject<GPTP>();
|
||||
gPTP2->SetNode(n2);
|
||||
gPTP2->SetMainClock(c2);
|
||||
gPTP2->AddDomain(0);
|
||||
gPTP2->AddPort(net2, GPTP::SLAVE, 0);
|
||||
gPTP2->SetAttribute("Priority", UintegerValue(0));
|
||||
n2->AddApplication(gPTP2);
|
||||
gPTP2->SetStartTime(Seconds(0));
|
||||
|
||||
Ptr<GPTP> gPTP3 = CreateObject<GPTP>();
|
||||
gPTP3->SetNode(n3);
|
||||
gPTP3->SetMainClock(c3);
|
||||
gPTP3->AddDomain(0);
|
||||
gPTP3->AddPort(net3_0, GPTP::SLAVE, 0);
|
||||
gPTP3->AddPort(net3_1, GPTP::MASTER, 0);
|
||||
gPTP3->AddPort(net3_2, GPTP::MASTER, 0);
|
||||
gPTP3->SetAttribute("Priority", UintegerValue(0));
|
||||
n3->AddApplication(gPTP3);
|
||||
gPTP3->SetStartTime(Seconds(0));
|
||||
|
||||
//Callback to displa information about GPTP execution
|
||||
gPTP1->TraceConnectWithoutContext("Pdelay", MakeBoundCallback(&PdelayCallback, Names::FindName(n1)));
|
||||
gPTP3->TraceConnectWithoutContext("Pdelay", MakeBoundCallback(&PdelayCallback, Names::FindName(n3)));
|
||||
gPTP1->TraceConnectWithoutContext("ClockAfterCorrection", MakeBoundCallback(&ClockAfterCorrectionCallback, Names::FindName(n1), c0));
|
||||
gPTP3->TraceConnectWithoutContext("ClockAfterCorrection", MakeBoundCallback(&ClockAfterCorrectionCallback, Names::FindName(n3), c0));
|
||||
|
||||
//Execute the simulation
|
||||
Simulator::Stop(Seconds(3));
|
||||
Simulator::Run();
|
||||
Simulator::Destroy();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user