200 lines
6.3 KiB
C++
200 lines
6.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 <bitset>
|
||
|
|
|
||
|
|
#include "ns3/tsn-node.h"
|
||
|
|
#include "ns3/tsn-net-device.h"
|
||
|
|
#include "ns3/ethernet-channel.h"
|
||
|
|
#include "ns3/ethernet-generator.h"
|
||
|
|
#include "ns3/ethernet-header2.h"
|
||
|
|
|
||
|
|
/**
|
||
|
|
* \file
|
||
|
|
*
|
||
|
|
* Example of the use of the use of the different TAS guard band mode on a 100Mb/s
|
||
|
|
* full duplex link with TAS on ES1 port
|
||
|
|
* ES1 ====== ES2
|
||
|
|
*
|
||
|
|
* This example script can be run using one of this two following commands
|
||
|
|
* according to the algorithm needed :
|
||
|
|
* ./ns3 run <path to the script> -- --none
|
||
|
|
* ./ns3 run <path to the script> -- --mtu
|
||
|
|
* ./ns3 run <path to the script> -- --pktsize
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
using namespace ns3;
|
||
|
|
|
||
|
|
NS_LOG_COMPONENT_DEFINE("Example");
|
||
|
|
|
||
|
|
//A callback to log the pkt reception
|
||
|
|
static void
|
||
|
|
MacRxCallback(std::string context, Ptr<const Packet> p)
|
||
|
|
{
|
||
|
|
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " received !" << p->ToString());
|
||
|
|
}
|
||
|
|
|
||
|
|
//A callback to log the pkt given to the netDevice by the application
|
||
|
|
static void
|
||
|
|
PktSentCallback(std::string context, Ptr<const Packet> p, uint16_t vid)
|
||
|
|
{
|
||
|
|
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " given to the netDevice !");
|
||
|
|
}
|
||
|
|
|
||
|
|
//A callback to log the pkt emission
|
||
|
|
static void
|
||
|
|
PhyTxCallback(std::string context, Ptr<const Packet> p)
|
||
|
|
{
|
||
|
|
NS_LOG_INFO((Simulator::Now()).As(Time::S) << " \t" << context << " : Pkt #" << p->GetUid() << " begin transmission !");
|
||
|
|
}
|
||
|
|
|
||
|
|
//A callback to log the gate update
|
||
|
|
static void
|
||
|
|
TasCallback(std::string context, uint8_t states)
|
||
|
|
{
|
||
|
|
Time t = Simulator::Now();
|
||
|
|
std::string str = "";
|
||
|
|
std::string binary = std::bitset<8>(states).to_string();
|
||
|
|
std::reverse(binary.begin(), binary.end());
|
||
|
|
|
||
|
|
for (int i = 0; i < (int)binary.length(); i++) {
|
||
|
|
str += " Fifo " + std::to_string(i);
|
||
|
|
std::string c{binary[i]};
|
||
|
|
int state = std::stoi(c);
|
||
|
|
|
||
|
|
if(state)
|
||
|
|
{
|
||
|
|
str += " Open ;";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
str += " Close;";
|
||
|
|
}
|
||
|
|
}
|
||
|
|
NS_LOG_INFO(context << " : At "<< t.GetNanoSeconds() <<" Tas gate states update :" << str);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
int
|
||
|
|
main(int argc, char* argv[])
|
||
|
|
{
|
||
|
|
//Enable logging
|
||
|
|
LogComponentEnable("Example", LOG_LEVEL_INFO);
|
||
|
|
LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO);
|
||
|
|
LogComponentEnable("Tas", LOG_LEVEL_INFO);
|
||
|
|
LogComponentEnable("TsnNetDevice", LOG_LEVEL_INFO);
|
||
|
|
|
||
|
|
//Command line interpretation
|
||
|
|
bool mtu = false;
|
||
|
|
bool pktsize = false;
|
||
|
|
bool none = false;
|
||
|
|
CommandLine cmd(__FILE__);
|
||
|
|
cmd.AddValue("mtu", "Enable mtu guard band mode", mtu);
|
||
|
|
cmd.AddValue("pktsize", "Enable pktsize guard band mode", pktsize);
|
||
|
|
cmd.AddValue("none", "Enable none guard band mode", none);
|
||
|
|
cmd.Parse(argc, argv);
|
||
|
|
if (mtu+pktsize+none > 1)
|
||
|
|
{
|
||
|
|
NS_LOG_INFO("Only one guard band mode can be selected");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
else if (mtu+pktsize+none == 0)
|
||
|
|
{
|
||
|
|
NS_LOG_INFO("A guard band mode must be selected using '--mtu' or '--pktsize' or '--none' ");
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
//Create two nodes
|
||
|
|
Ptr<TsnNode> n0 = CreateObject<TsnNode>();
|
||
|
|
Names::Add("ES1", n0);
|
||
|
|
Ptr<TsnNode> n1 = CreateObject<TsnNode>();
|
||
|
|
Names::Add("ES2", n1);
|
||
|
|
|
||
|
|
//Add perfect clock on each node
|
||
|
|
n0->AddClock(CreateObject<Clock>());
|
||
|
|
n1->AddClock(CreateObject<Clock>());
|
||
|
|
|
||
|
|
//Create and add a netDevice to each node
|
||
|
|
Ptr<TsnNetDevice> net0 = CreateObject<TsnNetDevice>();
|
||
|
|
net0->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s")));
|
||
|
|
n0->AddDevice(net0);
|
||
|
|
Names::Add("ES1#01", net0);
|
||
|
|
Ptr<TsnNetDevice> net1 = CreateObject<TsnNetDevice>();
|
||
|
|
net1->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/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>();
|
||
|
|
net0->Attach(channel);
|
||
|
|
net1->Attach(channel);
|
||
|
|
|
||
|
|
//Allocate a Mac address
|
||
|
|
net0->SetAddress(Mac48Address::Allocate());
|
||
|
|
net1->SetAddress(Mac48Address::Allocate());
|
||
|
|
|
||
|
|
//Create and add eight FIFO on each net device
|
||
|
|
for (int i=0; i<8; i++)
|
||
|
|
{
|
||
|
|
net0->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
net1->SetQueue(CreateObject<DropTailQueue<Packet>>());
|
||
|
|
}
|
||
|
|
|
||
|
|
//Set Tas Guard Band Mode (MTU is the default GuardBandMode)
|
||
|
|
if(mtu)
|
||
|
|
{
|
||
|
|
net0->GetTas()->SetAttribute("GuardBandMode", EnumValue(Tas::MTU));
|
||
|
|
}
|
||
|
|
else if(pktsize)
|
||
|
|
{
|
||
|
|
net0->GetTas()->SetAttribute("GuardBandMode", EnumValue(Tas::PKTSIZE));
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
net0->GetTas()->SetAttribute("GuardBandMode", EnumValue(Tas::NONE));
|
||
|
|
}
|
||
|
|
|
||
|
|
//Callback to display the gate update log (must be before StartTas() to display the initial gate states)
|
||
|
|
net0->GetTas()->TraceConnectWithoutContext("GatesUpdate", MakeBoundCallback(&TasCallback, Names::FindName(net0)));
|
||
|
|
|
||
|
|
//Add two GCL entry on net0 and start TAS
|
||
|
|
net0->AddGclEntry(Time(NanoSeconds(10)), 2);
|
||
|
|
net0->AddGclEntry(Time(NanoSeconds(4990)), 0);
|
||
|
|
net0->AddGclEntry(Time(MicroSeconds(95)), 2);
|
||
|
|
net0->AddGclEntry(Time(MicroSeconds(9900)), 0);
|
||
|
|
net0->AddGclEntry(Time(MilliSeconds(10)), 2);
|
||
|
|
net0->AddGclEntry(Time(MilliSeconds(20)), 0);
|
||
|
|
net0->StartTas();
|
||
|
|
|
||
|
|
//Application description
|
||
|
|
Ptr<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
|
||
|
|
app0->Setup(net0);
|
||
|
|
app0->SetAttribute("BurstSize", UintegerValue(1));
|
||
|
|
app0->SetAttribute("PayloadSize", UintegerValue(100));
|
||
|
|
app0->SetAttribute("Period", TimeValue(MilliSeconds(40)));
|
||
|
|
app0->SetAttribute("PCP", UintegerValue(1));
|
||
|
|
app0->SetAttribute("VlanID", UintegerValue(100));
|
||
|
|
n0->AddApplication(app0);
|
||
|
|
app0->SetStartTime(Seconds(0));
|
||
|
|
app0->SetStopTime(Seconds(4));
|
||
|
|
|
||
|
|
|
||
|
|
//Callback to display the packet transmitted and received log
|
||
|
|
app0->TraceConnectWithoutContext("PktSent", MakeBoundCallback(&PktSentCallback, Names::FindName(n0) + ":" + Names::FindName(net0)));
|
||
|
|
net0->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxCallback, Names::FindName(n0) + ":" + Names::FindName(net0)));
|
||
|
|
net1->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, Names::FindName(n1) + ":" + Names::FindName(net1)));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
//Execute the simulation
|
||
|
|
Simulator::Stop(MilliSeconds(30));
|
||
|
|
Simulator::Run();
|
||
|
|
Simulator::Destroy();
|
||
|
|
return 0;
|
||
|
|
}
|