#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 1SW in a 1Gb/s full duplex link as follow. * ES1 === \ / === ES2 * SW * 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 !"); } //Callbacks to log pkt drop static void MaxSDUSizeFilterDrop(std::string context, Ptr p) { NS_LOG_INFO(context << " : Packet #"<< p->GetUid() <<" was dropped by MaxSDUSizeFilter"); } static void REDFrameDrop(std::string context, Ptr p) { NS_LOG_INFO(context << " : Packet #"<< p->GetUid() <<" was dropped by Flow Meter"); } 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 = CreateObject("SW"); //Create Ethernet Channels and attach it to the netDevices Ptr l0 = CreateObject(); l0->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net1->Attach(l0); lan9668->GetPort(1)->Attach(l0); Ptr l1 = CreateObject(); l1->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net2->Attach(l1); lan9668->GetPort(2)->Attach(l1); Ptr l2 = CreateObject(); l2->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net3->Attach(l2); lan9668->GetPort(3)->Attach(l2); Ptr l3 = CreateObject(); l3->SetAttribute("Delay", TimeValue(MicroSeconds(0))); net4->Attach(l3); lan9668->GetPort(4)->Attach(l3); //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->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 10, {2}); lan9668->AddForwardingTableEntry(Mac48Address("ff:ff:ff:ff:ff:ff"), 10, {2, 3, 4}); lan9668->AddForwardingTableEntry(Mac48Address::ConvertFrom(net1->GetAddress()), 11, {1}); lan9668->AddForwardingTableEntry(Mac48Address::ConvertFrom(net4->GetAddress()), 12, {4}); lan9668->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 13, {2}); lan9668->AddForwardingTableEntry(Mac48Address::ConvertFrom(net2->GetAddress()), 14, {2}); //Add a null stream identification function on the switch for psfp Ptr sif = CreateObject(); sif->SetAttribute("VlanID", UintegerValue(10)); sif->SetAttribute("Address", AddressValue(Mac48Address::ConvertFrom(net2->GetAddress()))); lan9668->AddNullStreamIdentificationFunction(112, sif, {1}, {}, {}, {}); //Configure PSFP on the switch Ptr sfi0 = CreateObject(); sfi0->SetAttribute("StreamHandle", IntegerValue(112)); sfi0->SetAttribute("Priority", IntegerValue(-1)); //-1 = wildcard (like in PSFP MIB) sfi0->SetAttribute("MaxSDUSize", UintegerValue(1500)); lan9668->AddStreamFilter(sfi0); Ptr fm0 = CreateObject(); fm0->SetAttribute("CIR", DataRateValue(DataRate("40Mb/s"))); fm0->SetAttribute("CBS", UintegerValue(1500)); fm0->SetAttribute("DropOnYellow", BooleanValue(true)); fm0->SetAttribute("MarkAllFramesRedEnable", BooleanValue(false)); uint16_t fmid = lan9668->AddFlowMeter(fm0); sfi0->AddFlowMeterInstanceId(fmid); //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 related to PSFP event lan9668->GetPort(1)->TraceConnectWithoutContext("MaxSDUSizeFilterDrop", MakeBoundCallback(&MaxSDUSizeFilterDrop, Names::FindName(lan9668->GetPort(1)))); lan9668->GetPort(1)->TraceConnectWithoutContext("REDFrameDrop", MakeBoundCallback(&REDFrameDrop, Names::FindName(lan9668->GetPort(1)))); //Execute the simulation Simulator::Stop(MilliSeconds(300)); Simulator::Run(); Simulator::Destroy(); return 0; }