#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/timestamp-tag.h" #include "ns3/trace-helper.h" #include #include "ns3/tsn-node.h" #include "ns3/tsn-net-device.h" #include "ns3/switch-net-device.h" #include "ns3/ethernet-channel.h" #include "ns3/ethernet-generator.h" #include "ns3/ethernet-header2.h" #include "ns3/evb-lan9668.h" #include "ns3/stream-identification-function-null.h" #include "ns3/frer-match-recovery-function.h" #include "ns3/frer-vector-recovery-function.h" /** * \file * * Example with 4ES connected to 2SW in a 1Gb/s full duplex link as follow. * ES1 === \ /===\ / === ES2 * SW1 SW2 * ES3 === / \===/ \ === ES4 * */ 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 !"); } //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 pkt elimination due to FRER static void FrerDrop(std::string context, Ptr p) { NS_LOG_INFO(context << " : An instance of Packet #"<< p->GetUid() <<" was dropped by FRER recovery function"); } int main(int argc, char* argv[]) { //Enable logging LogComponentEnable("Example", LOG_LEVEL_INFO); LogComponentEnable("EthernetGenerator", LOG_LEVEL_INFO); LogComponentEnable("EvbLan9668", LOG_LEVEL_INFO); LogComponentEnable("TsnNetDevice", LOG_LEVEL_INFO); CommandLine cmd(__FILE__); cmd.Parse(argc, argv); //Create four end stations Ptr n1 = CreateObject(); Names::Add("ES1", n1); Ptr n2 = CreateObject(); Names::Add("ES2", n2); Ptr n3 = CreateObject(); Names::Add("ES3", n3); Ptr n4 = CreateObject(); Names::Add("ES4", n4); //Create and add a netDevices to each end station Ptr net1 = CreateObject(); n1->AddDevice(net1); Names::Add("ES1e#01", net1); Ptr net2 = CreateObject(); n2->AddDevice(net2); Names::Add("ES2#01", net2); Ptr net3 = CreateObject(); n3->AddDevice(net3); Names::Add("ES3#01", net3); Ptr net4 = CreateObject(); n4->AddDevice(net4); Names::Add("ES4#01", net4); //Allocate a Mac address to the end station net1->SetAddress(Mac48Address::Allocate()); net2->SetAddress(Mac48Address::Allocate()); net3->SetAddress(Mac48Address::Allocate()); net4->SetAddress(Mac48Address::Allocate()); //Create the switch Ptr lan9668_1 = CreateObject("SW1"); Ptr lan9668_2 = CreateObject("SW2"); //Create Ethernet Channels and attach it to the netDevices Ptr l0 = CreateObject(); l0->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net1->Attach(l0); lan9668_1->GetPort(1)->Attach(l0); Ptr l1 = CreateObject(); l1->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net2->Attach(l1); lan9668_2->GetPort(2)->Attach(l1); Ptr l2 = CreateObject(); l2->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net3->Attach(l2); lan9668_2->GetPort(1)->Attach(l2); Ptr l3 = CreateObject(); l3->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net4->Attach(l3); lan9668_1->GetPort(2)->Attach(l3); Ptr l4 = CreateObject(); l4->SetAttribute("Delay", TimeValue(MicroSeconds(0))); lan9668_1->GetPort(3)->Attach(l4); lan9668_2->GetPort(3)->Attach(l4); Ptr l5 = CreateObject(); l5->SetAttribute("Delay", TimeValue(MicroSeconds(0))); lan9668_1->GetPort(4)->Attach(l5); lan9668_2->GetPort(4)->Attach(l5); //Create and add eight FIFO on each end station net device for (int i=0; i<8; i++) { net1->SetQueue(CreateObject>()); net2->SetQueue(CreateObject>()); net3->SetQueue(CreateObject>()); net4->SetQueue(CreateObject>()); } //Add forwarding table entry lan9668_1->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 10, {3,4}); lan9668_2->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 10, {2}); //SW1 Stream identification and FRER configuration (replication) //Stream identification uint32_t streamHandle = 1; Ptr sif0 = CreateObject(); sif0->SetAttribute("VlanID", UintegerValue(10)); sif0->SetAttribute("Address", AddressValue(Mac48Address::ConvertFrom(net2->GetAddress()))); lan9668_1->AddNullStreamIdentificationFunction(streamHandle, sif0, {1}, {}, {}, {}); //Sequencing : Sequence generation Ptr seqf0 = CreateObject(); seqf0->SetAttribute("Direction", BooleanValue(false)); //in-facing seqf0->SetStreamHandle({streamHandle}); lan9668_1->AddSequenceGenerationFunction(seqf0); //Sequence encode Ptr seqEnc0 = CreateObject(); seqEnc0->SetAttribute("Direction", BooleanValue(false)); //in-facing seqEnc0->SetAttribute("Active", BooleanValue(true)); seqEnc0->SetStreamHandle({streamHandle}); lan9668_1->AddSequenceEncodeDecodeFunction(seqEnc0, 1); //SW2 Stream identification adn FRER configuration (elimination) //Stream identification Ptr sif1 = CreateObject(); sif1->SetAttribute("VlanID", UintegerValue(10)); sif1->SetAttribute("Address", AddressValue(Mac48Address::ConvertFrom(net2->GetAddress()))); lan9668_2->AddNullStreamIdentificationFunction(streamHandle, sif1, {}, {}, {2}, {}); //Sequence Decode Ptr seqEnc1 = CreateObject(); seqEnc1->SetAttribute("Direction", BooleanValue(false)); //in-facing seqEnc1->SetAttribute("Active", BooleanValue(false)); seqEnc1->SetStreamHandle({streamHandle}); lan9668_2->AddSequenceEncodeDecodeFunction(seqEnc1, 2); //Sequencing : Sequence recovery Ptr seqfreco0 = CreateObject(); seqfreco0->SetAttribute("Direction", BooleanValue(false)); //in-facing seqfreco0->SetAttribute("TakeNoSequence", BooleanValue(false)); seqfreco0->SetAttribute("IndividualRecovery", BooleanValue(false)); seqfreco0->SetStreamHandle({streamHandle}); //Sequencing : Sequence recovery : recovery function Ptr recf0 = CreateObject(); recf0->SetAttribute("ResetTimer", TimeValue(Seconds(1))); //Sequencing : Sequence recovery : latent error detection function Ptr latf0 = CreateObject(); latf0->SetAttribute("LatentErrorPaths", UintegerValue(2)); lan9668_2->AddSequenceRecoveryFunction(seqfreco0, recf0, latf0, {2}); //Application description Ptr app0 = CreateObject(); app0->Setup(net1); app0->SetAttribute("BurstSize", UintegerValue(1)); app0->SetAttribute("PayloadSize", UintegerValue(1478)); app0->SetAttribute("Period", TimeValue(MilliSeconds(100))); app0->SetAttribute("PCP", UintegerValue(4)); app0->SetAttribute("VlanID", UintegerValue(10)); app0->SetAttribute("Address", AddressValue(Mac48Address::ConvertFrom(net2->GetAddress()))); n1->AddApplication(app0); app0->SetStartTime(MilliSeconds(0)); app0->SetStopTime(MilliSeconds(200)); //Callback to display the packet transmitted and received log net1->TraceConnectWithoutContext("PhyTxBegin", MakeBoundCallback(&PhyTxCallback, Names::FindName(n1) + ":" + Names::FindName(net1))); net2->TraceConnectWithoutContext("MacRx", MakeBoundCallback(&MacRxCallback, Names::FindName(n2) + ":" + Names::FindName(net2))); //Callback to display elimination event lan9668_2->GetPort(2)->TraceConnectWithoutContext("FrerDrop", MakeBoundCallback(&FrerDrop, Names::FindName(lan9668_2->GetPort(2)))); //Execute the simulation Simulator::Stop(MilliSeconds(300)); Simulator::Run(); Simulator::Destroy(); return 0; }