Update README and add contrib dir

This commit is contained in:
2025-12-01 15:56:02 +01:00
parent 1b80de2153
commit cd9ba93d58
150 changed files with 25563 additions and 0 deletions

View File

@@ -0,0 +1,267 @@
#include "evb-lan9668.h"
#include "ns3/names.h"
#include "ns3/drop-tail-queue.h"
#include "ns3/cbs.h"
#include "ns3/tas.h"
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("EvbLan9668");
NS_OBJECT_ENSURE_REGISTERED(EvbLan9668);
TypeId
EvbLan9668::GetTypeId()
{
static TypeId tid =
TypeId("ns3::EvbLan9668")
.SetParent<Object>()
.SetGroupName("real-device")
.AddConstructor<EvbLan9668>();
return tid;
}
EvbLan9668::EvbLan9668()
{
NS_LOG_FUNCTION(this);
m_node = CreateObject<TsnNode>();
m_node->AddClock(CreateObject<Clock>()); //Add perfect clock
for (int i=0; i<m_portNumber; ++i){
Ptr<TsnNetDevice> net = CreateObject<TsnNetDevice>();
for (int j=0; j<m_queuesPerPort; ++j){
Ptr<DropTailQueue<Packet>> q = CreateObject<DropTailQueue<Packet>>();
q->SetAttribute("MaxSize", QueueSizeValue(m_fifoSize));
net->SetQueue(q);
}
m_node->AddDevice(net);
m_net_devices.insert(m_net_devices.end(), net);
}
m_switch_net_device = CreateObject<SwitchNetDevice>();
m_switch_net_device->SetAddress(Mac48Address::Allocate());
m_node->AddDevice(m_switch_net_device);
for (int i = 0; i < (int)m_net_devices.size(); i++){
m_switch_net_device->AddSwitchPort(m_net_devices[i]);
}
m_node->AddDevice(m_switch_net_device);
SetHardwareLimits();
}
EvbLan9668::EvbLan9668(std::string name): EvbLan9668()
{
NS_LOG_FUNCTION(this);
Names::Add(name, m_node);
for (int i = 0; i < (int)m_net_devices.size(); i++){
Names::Add(name + "-" + std::to_string(i) , m_net_devices[i]);
}
}
EvbLan9668::~EvbLan9668()
{
NS_LOG_FUNCTION(this);
}
void
EvbLan9668::SetHardwareLimits()
{
NS_LOG_FUNCTION(this);
//FDB
m_switch_net_device->SetAttribute("MaxPortNumber", UintegerValue(m_portNumber));
m_switch_net_device->SetAttribute("MaxFdbEntryNumber", UintegerValue(m_maxFdbEntryNumber));
m_switch_net_device->SetAttribute("MinForwardingLatency", TimeValue(m_minForwardingLatency));
m_switch_net_device->SetAttribute("MaxForwardingLatency", TimeValue(m_maxForwardingLatency));
//TAS
for (int i = 0; i < (int)m_net_devices.size(); i++){
m_net_devices[i]->GetTas()->SetAttribute("MaxGclEntryNumber", UintegerValue(m_maxGclEntryNumber));
m_net_devices[i]->GetTas()->SetAttribute("MaxGclCycleDuration", TimeValue(m_maxGclCycleDuration));
m_net_devices[i]->GetTas()->SetAttribute("MaxGclTimeInterval", TimeValue(m_maxGclTimeInterval));
}
//Stream identification
m_node->SetAttribute("MaxSidEntryNumber", UintegerValue(m_maxSidEntryNumber));
//PSFP
m_node->SetAttribute("MaxPsfpFilterEntryNumber", UintegerValue(m_maxPsfpFilterEntryNumber));
m_node->SetAttribute("MaxPsfpStreamGateEntryNumber", UintegerValue(m_maxPsfpStreamGateEntryNumber));
m_node->SetAttribute("MaxPsfpFlowMeterEntryNumber", UintegerValue(m_maxPsfpFlowMeterEntryNumber));
//FRER
m_node->SetAttribute("MaxFrerSeqGenEntryNumber", UintegerValue(m_maxFrerSeqGenEntryNumber));
m_node->SetAttribute("MaxFrerSeqRcvyEntryNumber", UintegerValue(m_maxFrerSeqRcvyEntryNumber));
m_node->SetAttribute("MaxFrerSeqEncEntryNumber", UintegerValue(m_maxFrerSeqEncEntryNumber));
}
Ptr<TsnNetDevice>
EvbLan9668::GetPort(int port_id)
{
NS_LOG_FUNCTION(this);
NS_ASSERT(port_id < (int) m_net_devices.size());
return m_net_devices[port_id];
}
void
EvbLan9668::SetPortDatarate(int port_id, DataRate d)
{
NS_LOG_FUNCTION(this);
NS_ASSERT_MSG(d == DataRate("10Mb/s") || d == DataRate("100Mb/s") || d == DataRate("1Gb/s"), "Trying to use a datarate not supported on this device (i.e 10Mb/s, 100Mb/s and 1Gb/s)");
GetPort(port_id)->SetAttribute("DataRate", DataRateValue(d));
}
void
EvbLan9668::AddForwardingTableEntry(Mac48Address dest, uint16_t vlan_id, std::vector<uint32_t> output_port_ids){
NS_LOG_FUNCTION(this);
std::vector<Ptr<NetDevice>> output_ports = {};
for (int i = 0; i < (int)output_port_ids.size(); i++){
output_ports.insert(output_ports.end(), GetPort(output_port_ids[i]));
}
m_switch_net_device->AddForwardingTableEntry(dest, vlan_id, output_ports);
}
void
EvbLan9668::AddCbs(uint32_t port_id, uint32_t queue_id, DataRate iddle_slope, DataRate port_transmit_rate)
{
NS_LOG_FUNCTION(this);
NS_ASSERT(queue_id < m_queuesPerPort);
Ptr<Cbs> cbs = CreateObject<Cbs>();
cbs->SetTsnNetDevice(GetPort(port_id));
cbs->SetAttribute("IdleSlope", DataRateValue(iddle_slope));
cbs->SetAttribute("MaxIdleSlope", DataRateValue(m_maxIddleSlope));
cbs->SetAttribute("portTransmitRate", DataRateValue(port_transmit_rate));
cbs->SetAttribute("MinLatencyOverhead", TimeValue(m_minCBSLatencyOverhead));
cbs->SetAttribute("MaxLatencyOverhead", TimeValue(m_maxCBSLatencyOverhead));
Ptr<DropTailQueue<Packet>> q = CreateObject<DropTailQueue<Packet>>();
q->SetAttribute("MaxSize", QueueSizeValue(m_fifoSize));
GetPort(port_id)->UpdateQueue(queue_id, q, cbs);
}
void
EvbLan9668::AddGclEntry(uint32_t port_id, Time interval, uint8_t state)
{
NS_LOG_FUNCTION(this);
GetPort(port_id)->AddGclEntry(interval, state);
}
void
EvbLan9668::StartTas()
{
NS_LOG_FUNCTION(this);
for (int i = 0; i < (int)m_net_devices.size(); i++){
m_net_devices[i]->StartTas();
}
}
void
EvbLan9668::AddNullStreamIdentificationFunction(
uint32_t streamHandle,
Ptr<NullStreamIdentificationFunction> streamIdentificationFunction,
std::vector<uint32_t> outFacInputPortIds,
std::vector<uint32_t> inFacInputPortIds,
std::vector<uint32_t> inFacOutputPortIds,
std::vector<uint32_t> outFacOutputPortIds)
{
NS_LOG_FUNCTION(this);
std::vector<Ptr<TsnNetDevice>> outFacInputPortList = {};
for (int i = 0; i < (int)outFacInputPortIds.size(); i++){
outFacInputPortList.insert(outFacInputPortList.end(), GetPort(outFacInputPortIds[i]));
}
std::vector<Ptr<TsnNetDevice>> inFacInputPortList = {};
for (int i = 0; i < (int)inFacInputPortIds.size(); i++){
inFacInputPortList.insert(inFacInputPortList.end(), GetPort(inFacInputPortIds[i]));
}
std::vector<Ptr<TsnNetDevice>> inFacOutputPortList = {};
for (int i = 0; i < (int)inFacOutputPortIds.size(); i++){
inFacOutputPortList.insert(inFacOutputPortList.end(), GetPort(inFacOutputPortIds[i]));
}
std::vector<Ptr<TsnNetDevice>> outFacOutputPortList = {};
for (int i = 0; i < (int)outFacOutputPortIds.size(); i++){
outFacOutputPortList.insert(outFacOutputPortList.end(), GetPort(outFacOutputPortIds[i]));
}
streamIdentificationFunction->SetAttribute("MinLatencyOverhead", TimeValue(m_minNullSIDLatencyOverhead));
streamIdentificationFunction->SetAttribute("MaxLatencyOverhead", TimeValue(m_maxNullSIDLatencyOverhead));
m_node->AddStreamIdentificationFunction(
streamHandle,
streamIdentificationFunction,
outFacInputPortList,
inFacInputPortList,
inFacOutputPortList,
outFacOutputPortList);
}
void
EvbLan9668::AddStreamFilter(Ptr<StreamFilterInstance> streamFilterInstance)
{
NS_LOG_FUNCTION(this);
m_node->AddStreamFilter(streamFilterInstance);
}
uint16_t
EvbLan9668::AddFlowMeter(Ptr<FlowMeterInstance> flowMeterInstance)
{
NS_LOG_FUNCTION(this);
return m_node->AddFlowMeter(flowMeterInstance);
}
void
EvbLan9668::AddSequenceGenerationFunction(Ptr<SequenceGenerationFunction> entry)
{
NS_LOG_FUNCTION(this);
m_node->AddSequenceGenerationFunction(entry);
}
void
EvbLan9668::AddSequenceRecoveryFunction(Ptr<SequenceRecoveryFunction> rcvy, Ptr<BaseRecoveryFunction> algo, Ptr<LatentErrorDetectionFunction> lat, std::vector<uint32_t> port_ids)
{
NS_LOG_FUNCTION(this);
rcvy->SetAttribute("MinLatencyOverhead", TimeValue(m_minFrerRcvyLatencyOverhead));
rcvy->SetAttribute("MaxLatencyOverhead", TimeValue(m_maxFrerRcvyLatencyOverhead));
algo->SetAttribute("MinResetTimer", TimeValue(m_minFrerSeqRcvyResetDuration));
algo->SetAttribute("MaxResetTimer", TimeValue(m_maxFrerSeqRcvyResetDuration));
lat->SetAttribute("MinTestTimer", TimeValue(m_minFrerLatErrorTestDuration));
lat->SetAttribute("MaxTestTimer", TimeValue(m_maxFrerLatErrorTestDuration));
lat->SetAttribute("MinResetTimer", TimeValue(m_minFrerLatErrorResetDuration));
lat->SetAttribute("MaxResetTimer", TimeValue(m_maxFrerLatErrorResetDuration));
std::vector<Ptr<TsnNetDevice>> ports = {};
for (int i = 0; i < (int)port_ids.size(); i++){
ports.insert(ports.end(), GetPort(port_ids[i]));
}
rcvy->SetPorts(ports);
rcvy->SetRecoveryFunction(algo);
lat->SetRecoveryFunction(algo);
rcvy->SetLatentErrorDetectionFunction(lat);
m_node->AddSequenceRecoveryFunction(rcvy);
}
void
EvbLan9668::AddSequenceEncodeDecodeFunction(Ptr<SequenceEncodeDecodeFunction> entry, uint32_t port_id)
{
NS_LOG_FUNCTION(this);
entry->SetPort(GetPort(port_id));
m_node->AddSequenceEncodeDecodeFunction(entry);
}
}

View File

@@ -0,0 +1,220 @@
#ifndef EVB_LAN9668_H
#define EVB_LAN9668_H
#include "ns3/object.h"
#include "ns3/tsn-node.h"
#include "ns3/tsn-net-device.h"
#include "ns3/stream-identification-function-null.h"
namespace ns3
{
/**
* \ingroup real-device
*
* \brief A object to simulate EVB-LAN9668 switch.
*/
class EvbLan9668: public Object
{
public:
/**
* \brief Get the TypeId
*
* \return The TypeId for this class
*/
static TypeId GetTypeId();
/**
* \brief Create a EvbLan9668
*/
EvbLan9668();
/**
* \brief Create a EvbLan9668
*/
EvbLan9668(std::string name);
/**
* Destroy a EvbLan9668
*
* This is the destructor for the TsnNode.
*/
~EvbLan9668();
// Delete copy constructor and assignment operator to avoid misuse
EvbLan9668& operator=(const EvbLan9668&) = delete;
EvbLan9668(const EvbLan9668&) = delete;
/**
* \brief Set most of the hardware limits
*/
void SetHardwareLimits();
/**
* \brief Get a TsnNetDevice from its port id
* \param id the port id
* \return The TsnNetDevice
*/
Ptr<TsnNetDevice> GetPort(int id);
/**
* \brief Add a entry in the forwarding database
* \param dest the mac address destination
* \param vlan_id the vlan id
* \param output_port_ids a vector of output port id
*/
void AddForwardingTableEntry(
Mac48Address dest,
uint16_t vlan_id,
std::vector<uint32_t> output_port_ids);
/**
* \brief Set the datarate of a port
* \param id the port id
* \param d the datarate
*/
void SetPortDatarate(int id, DataRate d);
/**
* \brief Add a CBS instance to a port and queue
* \para the port id
* \param the queue id
* \param the iddle_slope
* \param the port_transmit_rate
*/
void AddCbs(uint32_t port_id, uint32_t queue_id, DataRate iddle_slope, DataRate port_transmit_rate);
/**
* \brief Add a GCL entry to a port
* \para the port id
* \param the GCL entry duration
* \param the GCL entry state
*/
void AddGclEntry(uint32_t port_id, Time interval, uint8_t state);
/**
* \brief Start TAS operation
*/
void StartTas();
/**
* \brief Add a null stream identification function
* \para streamHandle
* \param stream Identification Function
* \param out-facing input port ids
* \param in-facing input port ids
* \param in-facing output port ids
* \param out-facing output port ids
*/
void
AddNullStreamIdentificationFunction(
uint32_t streamHandle,
Ptr<NullStreamIdentificationFunction> streamIdentificationFunction,
std::vector<uint32_t> outFacInputPortIds,
std::vector<uint32_t> inFacInputPortIds,
std::vector<uint32_t> inFacOutputPortIds,
std::vector<uint32_t> outFacOutputPortIds);
/**
* \brief Add a stream filter to the node
* \param the stream filter instance
*/
void
AddStreamFilter(Ptr<StreamFilterInstance> streamFilterInstance);
/**
* \brief Add a flow meter to the node
* \param the flow meter instance
*/
uint16_t
AddFlowMeter(Ptr<FlowMeterInstance> flowMeterInstance);
/**
* \brief Add generation function to the node
* \param the genertation function
*/
void
AddSequenceGenerationFunction(Ptr<SequenceGenerationFunction> entry);
/**
* \brief Add recovery function to the node
* \param the recovery function
* \param the recovery algo (match or vector)
* \param the latent error detection function
* \param the port ids
*/
void
AddSequenceRecoveryFunction(Ptr<SequenceRecoveryFunction> rcvy, Ptr<BaseRecoveryFunction> algo, Ptr<LatentErrorDetectionFunction> lat, std::vector<uint32_t> port_ids);
/**
* \brief Add encode/decode function to the node
* \param the encode/decode function
* \param the port id
*/
void
AddSequenceEncodeDecodeFunction(Ptr<SequenceEncodeDecodeFunction> entry, uint32_t port_id);
protected:
private:
Ptr<TsnNode> m_node;
std::vector<Ptr<TsnNetDevice>> m_net_devices;
Ptr<SwitchNetDevice> m_switch_net_device;
//Hardware limits
uint16_t m_portNumber = 8;
uint16_t m_queuesPerPort = 8;
uint16_t m_maxFdbEntryNumber = 64;
QueueSize m_fifoSize = QueueSize("102p");
Time m_minForwardingLatency = NanoSeconds(2660); //2660
Time m_maxForwardingLatency = NanoSeconds(2370); //2370
//CBS
DataRate m_maxIddleSlope = DataRate("3.282Gb/s");
Time m_minCBSLatencyOverhead = NanoSeconds(0); //-25ns
Time m_maxCBSLatencyOverhead = NanoSeconds(0); //-9ns
//Tas
uint32_t m_maxGclEntryNumber = 256;
Time m_maxGclCycleDuration = NanoSeconds(999999999);
Time m_maxGclTimeInterval = NanoSeconds(999999999);
Time m_minTASLatencyOverhead = NanoSeconds(0);
Time m_maxTASLatencyOverhead = NanoSeconds(0);
//Stream identification
uint32_t m_maxSidEntryNumber = 127;
Time m_minNullSIDLatencyOverhead = NanoSeconds(0); //-9ns
Time m_maxNullSIDLatencyOverhead = NanoSeconds(0); //-13ns
Time m_minSourceMacSIDLatencyOverhead = NanoSeconds(0);
Time m_maxSourceMacSIDLatencyOverhead = NanoSeconds(0);
//PSFP
uint32_t m_maxPsfpFilterEntryNumber = 176;
uint32_t m_maxPsfpStreamGateEntryNumber = 176;
uint32_t m_maxPsfpFlowMeterEntryNumber = 240;
//FRER
uint32_t m_maxFrerSeqGenEntryNumber = 99;
uint32_t m_maxFrerSeqRcvyEntryNumber = 99;
uint32_t m_maxFrerSeqEncEntryNumber = 99;
Time m_minFrerSeqRcvyResetDuration = MilliSeconds(1);
Time m_maxFrerSeqRcvyResetDuration = Seconds(4.095);
Time m_minFrerLatErrorTestDuration = Seconds(1);
Time m_maxFrerLatErrorTestDuration = Seconds(86400);
Time m_minFrerLatErrorResetDuration = Seconds(1);
Time m_maxFrerLatErrorResetDuration = Seconds(86400);
Time m_minFrerRcvyLatencyOverhead = NanoSeconds(40); //40ns
Time m_maxFrerRcvyLatencyOverhead = NanoSeconds(40); //40ns
};
}
#endif /* EVB_LAN9668_H */