124 lines
4.3 KiB
C++
124 lines
4.3 KiB
C++
|
|
#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/ethernet-channel.h"
|
||
|
|
#include "ns3/clock.h"
|
||
|
|
#include "ns3/clock-fix-precision.h"
|
||
|
|
#include "ns3/gPTP.h"
|
||
|
|
|
||
|
|
/**
|
||
|
|
* \file
|
||
|
|
*
|
||
|
|
* Example of the use of gPTP on a network composed of two end-stations
|
||
|
|
* connected by a 1Gb/s full duplex link. ES1 is the GPTP Grandmaster.
|
||
|
|
* This exemple use fix precision clock (non realistic clock made for
|
||
|
|
* research purpose)
|
||
|
|
* ES1 ====== 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("GPTP", LOG_LEVEL_INFO);
|
||
|
|
|
||
|
|
CommandLine cmd(__FILE__);
|
||
|
|
cmd.Parse(argc, argv);
|
||
|
|
|
||
|
|
//Create two nodes
|
||
|
|
Ptr<TsnNode> n0 = CreateObject<TsnNode>();
|
||
|
|
Names::Add("ES1", n0);
|
||
|
|
Ptr<TsnNode> n1 = CreateObject<TsnNode>();
|
||
|
|
Names::Add("ES2", n1);
|
||
|
|
|
||
|
|
|
||
|
|
//Create and add clock to TsnNode
|
||
|
|
Ptr<Clock> c0 = CreateObject<Clock>(); //Perfect clock
|
||
|
|
n0->SetMainClock(c0);
|
||
|
|
|
||
|
|
Ptr<FixPrecisionClock> c1 = CreateObject<FixPrecisionClock>();
|
||
|
|
c1->SetAttribute("Precision", TimeValue(NanoSeconds(100)));
|
||
|
|
c1->SetRefClock(c0); //Set GM clock as reference
|
||
|
|
n1->SetMainClock(c1);
|
||
|
|
|
||
|
|
//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);
|
||
|
|
|
||
|
|
//Create a Ethernet Channel and attach it two the two netDevices
|
||
|
|
Ptr<EthernetChannel> channel = CreateObject<EthernetChannel>();
|
||
|
|
channel->SetAttribute("Delay", TimeValue(Time(NanoSeconds(200))));
|
||
|
|
net0->Attach(channel);
|
||
|
|
net1->Attach(channel);
|
||
|
|
|
||
|
|
//Allocate a Mac address
|
||
|
|
net0->SetAddress(Mac48Address::Allocate());
|
||
|
|
net1->SetAddress(Mac48Address::Allocate());
|
||
|
|
|
||
|
|
//Add two fifo per netdevice.
|
||
|
|
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net1->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(1));
|
||
|
|
n0->AddApplication(gPTP0);
|
||
|
|
gPTP0->SetStartTime(Seconds(0));
|
||
|
|
|
||
|
|
Ptr<GPTP> gPTP1 = CreateObject<GPTP>();
|
||
|
|
gPTP1->SetNode(n1);
|
||
|
|
gPTP1->SetMainClock(c1);
|
||
|
|
gPTP1->AddDomain(0, c1);
|
||
|
|
gPTP1->AddPort(net1, GPTP::SLAVE, 0);
|
||
|
|
gPTP1->SetAttribute("Priority", UintegerValue(1));
|
||
|
|
n1->AddApplication(gPTP1);
|
||
|
|
gPTP1->SetStartTime(Seconds(0));
|
||
|
|
|
||
|
|
//Callback to displa information about GPTP execution
|
||
|
|
gPTP1->TraceConnectWithoutContext("Pdelay", MakeBoundCallback(&PdelayCallback, Names::FindName(n1)));
|
||
|
|
gPTP1->TraceConnectWithoutContext("ClockAfterCorrection", MakeBoundCallback(&ClockAfterCorrectionCallback, Names::FindName(n1), c0));
|
||
|
|
|
||
|
|
//Execute the simulation
|
||
|
|
Simulator::Stop(Seconds(5));
|
||
|
|
Simulator::Run();
|
||
|
|
Simulator::Destroy();
|
||
|
|
return 0;
|
||
|
|
}
|