diff --git a/contrib/real-device/CMakeLists.txt b/contrib/real-device/CMakeLists.txt index c98ba41..727512d 100644 --- a/contrib/real-device/CMakeLists.txt +++ b/contrib/real-device/CMakeLists.txt @@ -12,9 +12,11 @@ endif() build_lib( LIBNAME real-device - SOURCE_FILES model/evb-lan9668.cc + SOURCE_FILES model/real-switch.cc + model/evb-lan9668.cc helper/real-device-helper.cc - HEADER_FILES model/evb-lan9668.h + HEADER_FILES model/real-switch.h + model/evb-lan9668.h helper/real-device-helper.h LIBRARIES_TO_LINK ${libcore} ${libethernet} diff --git a/contrib/real-device/model/evb-lan9668.cc b/contrib/real-device/model/evb-lan9668.cc index 6e810f1..9e7c95e 100644 --- a/contrib/real-device/model/evb-lan9668.cc +++ b/contrib/real-device/model/evb-lan9668.cc @@ -18,7 +18,7 @@ EvbLan9668::GetTypeId() { static TypeId tid = TypeId("ns3::EvbLan9668") - .SetParent() + .SetParent() .SetGroupName("real-device") .AddConstructor(); return tid; @@ -27,6 +27,8 @@ EvbLan9668::GetTypeId() EvbLan9668::EvbLan9668() { NS_LOG_FUNCTION(this); + UpdateParentHardwareCharacteristics(); + m_node = CreateObject(); m_node->AddClock(CreateObject()); //Add perfect clock @@ -69,199 +71,54 @@ EvbLan9668::~EvbLan9668() } void -EvbLan9668::SetHardwareLimits() +EvbLan9668::UpdateParentHardwareCharacteristics() { - 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)); + NS_LOG_FUNCTION(this); + + //Hardware limits + m_portNumber = 8; + m_queuesPerPort = 8; + m_maxFdbEntryNumber = 64; + m_fifoSize = QueueSize("102p"); + m_minForwardingLatency = NanoSeconds(2660); //2660 + m_maxForwardingLatency = NanoSeconds(2370); //2370 - //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)); - } + //CBS + m_maxIddleSlope = DataRate("3.282Gb/s"); + m_minCBSLatencyOverhead = NanoSeconds(0); //-25ns + m_maxCBSLatencyOverhead = NanoSeconds(0); //-9ns - //Stream identification - m_node->SetAttribute("MaxSidEntryNumber", UintegerValue(m_maxSidEntryNumber)); + //Tas + m_maxGclEntryNumber = 256; + m_maxGclCycleDuration = NanoSeconds(999999999); + m_maxGclTimeInterval = NanoSeconds(999999999); + m_minTASLatencyOverhead = NanoSeconds(0); + m_maxTASLatencyOverhead = NanoSeconds(0); - //PSFP - m_node->SetAttribute("MaxPsfpFilterEntryNumber", UintegerValue(m_maxPsfpFilterEntryNumber)); - m_node->SetAttribute("MaxPsfpStreamGateEntryNumber", UintegerValue(m_maxPsfpStreamGateEntryNumber)); - m_node->SetAttribute("MaxPsfpFlowMeterEntryNumber", UintegerValue(m_maxPsfpFlowMeterEntryNumber)); + //Stream identification + m_maxSidEntryNumber = 127; + m_minNullSIDLatencyOverhead = NanoSeconds(0); //-9ns + m_maxNullSIDLatencyOverhead = NanoSeconds(0); //-13ns + m_minSourceMacSIDLatencyOverhead = NanoSeconds(0); + m_maxSourceMacSIDLatencyOverhead = NanoSeconds(0); - //FRER - m_node->SetAttribute("MaxFrerSeqGenEntryNumber", UintegerValue(m_maxFrerSeqGenEntryNumber)); - m_node->SetAttribute("MaxFrerSeqRcvyEntryNumber", UintegerValue(m_maxFrerSeqRcvyEntryNumber)); - m_node->SetAttribute("MaxFrerSeqEncEntryNumber", UintegerValue(m_maxFrerSeqEncEntryNumber)); + //PSFP + m_maxPsfpFilterEntryNumber = 176; + m_maxPsfpStreamGateEntryNumber = 176; + m_maxPsfpFlowMeterEntryNumber = 240; + + //FRER + m_maxFrerSeqGenEntryNumber = 99; + m_maxFrerSeqRcvyEntryNumber = 99; + m_maxFrerSeqEncEntryNumber = 99; + m_minFrerSeqRcvyResetDuration = MilliSeconds(1); + m_maxFrerSeqRcvyResetDuration = Seconds(4.095); + m_minFrerLatErrorTestDuration = Seconds(1); + m_maxFrerLatErrorTestDuration = Seconds(86400); + m_minFrerLatErrorResetDuration = Seconds(1); + m_maxFrerLatErrorResetDuration = Seconds(86400); + m_minFrerRcvyLatencyOverhead = NanoSeconds(40); //40ns + m_maxFrerRcvyLatencyOverhead = NanoSeconds(40); //40ns } - -Ptr -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 output_port_ids){ - NS_LOG_FUNCTION(this); - std::vector> 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 = CreateObject(); - 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> q = CreateObject>(); - 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 streamIdentificationFunction, - std::vector outFacInputPortIds, - std::vector inFacInputPortIds, - std::vector inFacOutputPortIds, - std::vector outFacOutputPortIds) -{ - NS_LOG_FUNCTION(this); - - std::vector> outFacInputPortList = {}; - for (int i = 0; i < (int)outFacInputPortIds.size(); i++){ - outFacInputPortList.insert(outFacInputPortList.end(), GetPort(outFacInputPortIds[i])); - } - - std::vector> inFacInputPortList = {}; - for (int i = 0; i < (int)inFacInputPortIds.size(); i++){ - inFacInputPortList.insert(inFacInputPortList.end(), GetPort(inFacInputPortIds[i])); - } - - std::vector> inFacOutputPortList = {}; - for (int i = 0; i < (int)inFacOutputPortIds.size(); i++){ - inFacOutputPortList.insert(inFacOutputPortList.end(), GetPort(inFacOutputPortIds[i])); - } - - std::vector> 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) -{ - NS_LOG_FUNCTION(this); - m_node->AddStreamFilter(streamFilterInstance); -} - -uint16_t -EvbLan9668::AddFlowMeter(Ptr flowMeterInstance) -{ - NS_LOG_FUNCTION(this); - return m_node->AddFlowMeter(flowMeterInstance); -} - - -void -EvbLan9668::AddSequenceGenerationFunction(Ptr entry) -{ - NS_LOG_FUNCTION(this); - m_node->AddSequenceGenerationFunction(entry); -} - -void -EvbLan9668::AddSequenceRecoveryFunction(Ptr rcvy, Ptr algo, Ptr lat, std::vector 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> 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 entry, uint32_t port_id) -{ - NS_LOG_FUNCTION(this); - entry->SetPort(GetPort(port_id)); - m_node->AddSequenceEncodeDecodeFunction(entry); -} - - } diff --git a/contrib/real-device/model/evb-lan9668.h b/contrib/real-device/model/evb-lan9668.h index 79fcaa3..ae4c815 100644 --- a/contrib/real-device/model/evb-lan9668.h +++ b/contrib/real-device/model/evb-lan9668.h @@ -1,14 +1,12 @@ #ifndef EVB_LAN9668_H #define EVB_LAN9668_H -#include "ns3/object.h" +#include "ns3/real-switch.h" #include "ns3/tsn-node.h" #include "ns3/tsn-net-device.h" #include "ns3/stream-identification-function-null.h" - - namespace ns3 { @@ -17,7 +15,7 @@ namespace ns3 * * \brief A object to simulate EVB-LAN9668 switch. */ - class EvbLan9668: public Object + class EvbLan9668: public RealSwitch { public: @@ -49,170 +47,15 @@ namespace ns3 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 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 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 streamIdentificationFunction, - std::vector outFacInputPortIds, - std::vector inFacInputPortIds, - std::vector inFacOutputPortIds, - std::vector outFacOutputPortIds); - - - /** - * \brief Add a stream filter to the node - * \param the stream filter instance - */ - void - AddStreamFilter(Ptr streamFilterInstance); - - /** - * \brief Add a flow meter to the node - * \param the flow meter instance - */ - uint16_t - AddFlowMeter(Ptr flowMeterInstance); - - /** - * \brief Add generation function to the node - * \param the genertation function - */ - void - AddSequenceGenerationFunction(Ptr 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 rcvy, Ptr algo, Ptr lat, std::vector port_ids); - - /** - * \brief Add encode/decode function to the node - * \param the encode/decode function - * \param the port id - */ - void - AddSequenceEncodeDecodeFunction(Ptr entry, uint32_t port_id); - - protected: + /** + * Update the parent hardware characteristics with the child values + */ + void UpdateParentHardwareCharacteristics() override; + + private: - Ptr m_node; - std::vector> m_net_devices; - Ptr 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 - }; } diff --git a/contrib/real-device/model/real-switch.cc b/contrib/real-device/model/real-switch.cc new file mode 100644 index 0000000..da96e01 --- /dev/null +++ b/contrib/real-device/model/real-switch.cc @@ -0,0 +1,274 @@ +#include "real-switch.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("RealSwitch"); + +NS_OBJECT_ENSURE_REGISTERED(RealSwitch); + +TypeId +RealSwitch::GetTypeId() +{ + static TypeId tid = + TypeId("ns3::RealSwitch") + .SetParent() + .SetGroupName("real-device") + .AddConstructor(); + return tid; +} + +RealSwitch::RealSwitch() +{ + NS_LOG_FUNCTION(this); + + m_node = CreateObject(); + m_node->AddClock(CreateObject()); //Add perfect clock + + for (int i=0; i net = CreateObject(); + for (int j=0; j> q = CreateObject>(); + 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(); + 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(); +} + +RealSwitch::RealSwitch(std::string name): RealSwitch() +{ + 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]); + } +} + +RealSwitch::~RealSwitch() +{ + NS_LOG_FUNCTION(this); +} + +void +RealSwitch::UpdateParentHardwareCharacteristics() +{ + NS_LOG_FUNCTION(this); +} + +void +RealSwitch::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 +RealSwitch::GetPort(int port_id) +{ + NS_LOG_FUNCTION(this); + NS_ASSERT(port_id < (int) m_net_devices.size()); + return m_net_devices[port_id]; +} + +void +RealSwitch::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 +RealSwitch::AddForwardingTableEntry(Mac48Address dest, uint16_t vlan_id, std::vector output_port_ids){ + NS_LOG_FUNCTION(this); + std::vector> 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 +RealSwitch::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 = CreateObject(); + 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> q = CreateObject>(); + q->SetAttribute("MaxSize", QueueSizeValue(m_fifoSize)); + + GetPort(port_id)->UpdateQueue(queue_id, q, cbs); +} + +void +RealSwitch::AddGclEntry(uint32_t port_id, Time interval, uint8_t state) +{ + NS_LOG_FUNCTION(this); + GetPort(port_id)->AddGclEntry(interval, state); +} + +void +RealSwitch::StartTas() +{ + NS_LOG_FUNCTION(this); + for (int i = 0; i < (int)m_net_devices.size(); i++){ + m_net_devices[i]->StartTas(); + } +} + +void +RealSwitch::AddNullStreamIdentificationFunction( + uint32_t streamHandle, + Ptr streamIdentificationFunction, + std::vector outFacInputPortIds, + std::vector inFacInputPortIds, + std::vector inFacOutputPortIds, + std::vector outFacOutputPortIds) +{ + NS_LOG_FUNCTION(this); + + std::vector> outFacInputPortList = {}; + for (int i = 0; i < (int)outFacInputPortIds.size(); i++){ + outFacInputPortList.insert(outFacInputPortList.end(), GetPort(outFacInputPortIds[i])); + } + + std::vector> inFacInputPortList = {}; + for (int i = 0; i < (int)inFacInputPortIds.size(); i++){ + inFacInputPortList.insert(inFacInputPortList.end(), GetPort(inFacInputPortIds[i])); + } + + std::vector> inFacOutputPortList = {}; + for (int i = 0; i < (int)inFacOutputPortIds.size(); i++){ + inFacOutputPortList.insert(inFacOutputPortList.end(), GetPort(inFacOutputPortIds[i])); + } + + std::vector> 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 +RealSwitch::AddStreamFilter(Ptr streamFilterInstance) +{ + NS_LOG_FUNCTION(this); + m_node->AddStreamFilter(streamFilterInstance); +} + +uint16_t +RealSwitch::AddFlowMeter(Ptr flowMeterInstance) +{ + NS_LOG_FUNCTION(this); + return m_node->AddFlowMeter(flowMeterInstance); +} + + +void +RealSwitch::AddSequenceGenerationFunction(Ptr entry) +{ + NS_LOG_FUNCTION(this); + m_node->AddSequenceGenerationFunction(entry); +} + +void +RealSwitch::AddSequenceRecoveryFunction(Ptr rcvy, Ptr algo, Ptr lat, std::vector 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> 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 +RealSwitch::AddSequenceEncodeDecodeFunction(Ptr entry, uint32_t port_id) +{ + NS_LOG_FUNCTION(this); + entry->SetPort(GetPort(port_id)); + m_node->AddSequenceEncodeDecodeFunction(entry); +} + + +} diff --git a/contrib/real-device/model/real-switch.h b/contrib/real-device/model/real-switch.h new file mode 100644 index 0000000..a93120f --- /dev/null +++ b/contrib/real-device/model/real-switch.h @@ -0,0 +1,228 @@ +#ifndef REAL_SWITCH_H +#define REAL_SWITCH_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 real switch. + */ + class RealSwitch: public Object + { + public: + + /** + * \brief Get the TypeId + * + * \return The TypeId for this class + */ + static TypeId GetTypeId(); + + /** + * \brief Create a RealSwitch + */ + RealSwitch(); + + /** + * \brief Create a RealSwitch + */ + RealSwitch(std::string name); + + /** + * Destroy a RealSwitch + * + * This is the destructor for the TsnNode. + */ + ~RealSwitch(); + + // Delete copy constructor and assignment operator to avoid misuse + RealSwitch& operator=(const RealSwitch&) = delete; + RealSwitch(const RealSwitch&) = 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 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 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 streamIdentificationFunction, + std::vector outFacInputPortIds, + std::vector inFacInputPortIds, + std::vector inFacOutputPortIds, + std::vector outFacOutputPortIds); + + + /** + * \brief Add a stream filter to the node + * \param the stream filter instance + */ + void + AddStreamFilter(Ptr streamFilterInstance); + + /** + * \brief Add a flow meter to the node + * \param the flow meter instance + */ + uint16_t + AddFlowMeter(Ptr flowMeterInstance); + + /** + * \brief Add generation function to the node + * \param the genertation function + */ + void + AddSequenceGenerationFunction(Ptr 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 rcvy, Ptr algo, Ptr lat, std::vector port_ids); + + /** + * \brief Add encode/decode function to the node + * \param the encode/decode function + * \param the port id + */ + void + AddSequenceEncodeDecodeFunction(Ptr entry, uint32_t port_id); + + + protected: + + /** + * Update the parent hardware characteristics with the child values + */ + virtual void UpdateParentHardwareCharacteristics(); + + + Ptr m_node; + std::vector> m_net_devices; + Ptr m_switch_net_device; + + + //Hardware limits + uint16_t m_portNumber = 0; + uint16_t m_queuesPerPort = 8; + uint16_t m_maxFdbEntryNumber = 0; + QueueSize m_fifoSize = QueueSize("0p"); + Time m_minForwardingLatency = Seconds(0); + Time m_maxForwardingLatency = Seconds(0); + + //CBS + DataRate m_maxIddleSlope = DataRate("0Gb/s"); + Time m_minCBSLatencyOverhead = Seconds(0); + Time m_maxCBSLatencyOverhead = Seconds(0); + + //Tas + uint32_t m_maxGclEntryNumber = 0; + Time m_maxGclCycleDuration = Seconds(0); + Time m_maxGclTimeInterval = Seconds(0); + Time m_minTASLatencyOverhead = Seconds(0); + Time m_maxTASLatencyOverhead = Seconds(0); + + //Stream identification + uint32_t m_maxSidEntryNumber = 0; + Time m_minNullSIDLatencyOverhead = Seconds(0); + Time m_maxNullSIDLatencyOverhead = Seconds(0); + Time m_minSourceMacSIDLatencyOverhead = Seconds(0); + Time m_maxSourceMacSIDLatencyOverhead = Seconds(0); + + //PSFP + uint32_t m_maxPsfpFilterEntryNumber = 0; + uint32_t m_maxPsfpStreamGateEntryNumber = 0; + uint32_t m_maxPsfpFlowMeterEntryNumber = 0; + + //FRER + uint32_t m_maxFrerSeqGenEntryNumber = 0; + uint32_t m_maxFrerSeqRcvyEntryNumber = 0; + uint32_t m_maxFrerSeqEncEntryNumber = 0; + Time m_minFrerSeqRcvyResetDuration = Seconds(0); + Time m_maxFrerSeqRcvyResetDuration = Seconds(0); + Time m_minFrerLatErrorTestDuration = Seconds(0); + Time m_maxFrerLatErrorTestDuration = Seconds(0); + Time m_minFrerLatErrorResetDuration = Seconds(0); + Time m_maxFrerLatErrorResetDuration = Seconds(0); + Time m_minFrerRcvyLatencyOverhead = Seconds(0); + Time m_maxFrerRcvyLatencyOverhead = Seconds(0); + + private: + }; + +} + +#endif /* REAL_SWITCH_H */