#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 #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 -- --none * ./ns3 run -- --mtu * ./ns3 run -- --pktsize * */ using namespace ns3; NS_LOG_COMPONENT_DEFINE("Example"); //A callback to log the pkt reception static void MacRxCallback(std::string context, Ptr 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 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 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 n0 = CreateObject(); Names::Add("ES1", n0); Ptr n1 = CreateObject(); Names::Add("ES2", n1); //Add perfect clock on each node n0->AddClock(CreateObject()); n1->AddClock(CreateObject()); //Create and add a netDevice to each node Ptr net0 = CreateObject(); net0->SetAttribute("DataRate", DataRateValue(DataRate("100Mb/s"))); n0->AddDevice(net0); Names::Add("ES1#01", net0); Ptr net1 = CreateObject(); 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 channel = CreateObject(); 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>()); net1->SetQueue(CreateObject>()); } //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 app0 = CreateObject(); 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; }