Files

195 lines
7.3 KiB
C++
Raw Permalink Normal View History

2025-12-01 15:56:02 +01:00
#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 <fstream>
#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<const Packet> 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<const Packet> 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<const Packet> p)
{
NS_LOG_INFO(context << " : Packet #"<< p->GetUid() <<" was dropped by MaxSDUSizeFilter");
}
static void
REDFrameDrop(std::string context, Ptr<const Packet> 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<TsnNode> n1 = CreateObject<TsnNode>();
Names::Add("ES1", n1);
Ptr<TsnNode> n2 = CreateObject<TsnNode>();
Names::Add("ES2", n2);
Ptr<TsnNode> n3 = CreateObject<TsnNode>();
Names::Add("ES3", n3);
Ptr<TsnNode> n4 = CreateObject<TsnNode>();
Names::Add("ES4", n4);
//Create and add a netDevices to each end station
Ptr<TsnNetDevice> net1 = CreateObject<TsnNetDevice>();
n1->AddDevice(net1);
Names::Add("ES1e#01", net1);
Ptr<TsnNetDevice> net2 = CreateObject<TsnNetDevice>();
n2->AddDevice(net2);
Names::Add("ES2#01", net2);
Ptr<TsnNetDevice> net3 = CreateObject<TsnNetDevice>();
n3->AddDevice(net3);
Names::Add("ES3#01", net3);
Ptr<TsnNetDevice> net4 = CreateObject<TsnNetDevice>();
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<EvbLan9668> lan9668 = CreateObject<EvbLan9668>("SW");
//Create Ethernet Channels and attach it to the netDevices
Ptr<EthernetChannel> l0 = CreateObject<EthernetChannel>();
l0->SetAttribute("Delay", TimeValue(MicroSeconds(0)));
net1->Attach(l0);
lan9668->GetPort(1)->Attach(l0);
Ptr<EthernetChannel> l1 = CreateObject<EthernetChannel>();
l1->SetAttribute("Delay", TimeValue(MicroSeconds(0)));
net2->Attach(l1);
lan9668->GetPort(2)->Attach(l1);
Ptr<EthernetChannel> l2 = CreateObject<EthernetChannel>();
l2->SetAttribute("Delay", TimeValue(MicroSeconds(0)));
net3->Attach(l2);
lan9668->GetPort(3)->Attach(l2);
Ptr<EthernetChannel> l3 = CreateObject<EthernetChannel>();
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<DropTailQueue<Packet>>());
net2->SetQueue(CreateObject<DropTailQueue<Packet>>());
net3->SetQueue(CreateObject<DropTailQueue<Packet>>());
net4->SetQueue(CreateObject<DropTailQueue<Packet>>());
}
//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<NullStreamIdentificationFunction> sif = CreateObject<NullStreamIdentificationFunction>();
sif->SetAttribute("VlanID", UintegerValue(10));
sif->SetAttribute("Address", AddressValue(Mac48Address::ConvertFrom(net2->GetAddress())));
lan9668->AddNullStreamIdentificationFunction(112, sif, {1}, {}, {}, {});
//Configure PSFP on the switch
Ptr<StreamFilterInstance> sfi0 = CreateObject<StreamFilterInstance>();
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<FlowMeterInstance> fm0 = CreateObject<FlowMeterInstance>();
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<EthernetGenerator> app0 = CreateObject<EthernetGenerator>();
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;
}