Files
eden-sim/contrib/tsn/model/cbs.cc

193 lines
5.0 KiB
C++
Raw Normal View History

2025-12-01 15:56:02 +01:00
#include "cbs.h"
#include "ns3/tsn-transmission-selection-algo.h"
#include "ns3/log.h"
#include "ns3/nstime.h"
#include "ns3/uinteger.h"
#include "ns3/data-rate.h"
#include "ns3/simulator.h"
#include "ns3/traced-callback.h"
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("Cbs");
NS_OBJECT_ENSURE_REGISTERED(Cbs);
TypeId
Cbs::GetTypeId()
{
static TypeId tid =
TypeId("ns3::Cbs")
.SetParent<TsnTransmissionSelectionAlgo>()
.SetGroupName("Tsn")
.AddConstructor<Cbs>()
.AddAttribute("IdleSlope",
"CBS idle slope parameter in bit/s",
DataRateValue(DataRate("1Gb/s")),
MakeDataRateAccessor(&Cbs::m_idleSlope),
MakeDataRateChecker())
.AddAttribute("portTransmitRate",
"CBS port transmit rate parameter in bit/s",
DataRateValue(DataRate("1Gb/s")),
MakeDataRateAccessor(&Cbs::m_portTransmitRate),
MakeDataRateChecker())
.AddTraceSource("Credit",
"CBS credit",
MakeTraceSourceAccessor(&Cbs::m_creditTrace),
"ns3::TracedValueCallback::double")
.AddAttribute("MaxIdleSlope",
"CBS idle slope parameter in bit/s",
DataRateValue(DataRate("1000Gb/s")),
MakeDataRateAccessor(&Cbs::m_maxIdleSlope),
MakeDataRateChecker());
return tid;
}
Cbs::Cbs()
{
NS_LOG_FUNCTION(this);
m_credit = 0;
m_state = IDLE;
m_transmissionGateIsOpen = true;
m_lastUpdateCreditTime = Simulator::Now();
}
Cbs::~Cbs()
{
NS_LOG_FUNCTION(this);
}
bool
Cbs::IsReadyToTransmit()
{
NS_LOG_FUNCTION(this);
if(m_credit>=0){
return true;
}
else{
m_state = WAITING;
return false;
}
}
2025-12-02 11:43:04 +01:00
void
Cbs::Update()
{
NS_LOG_FUNCTION(this);
if (m_state != TRANSMITTING)
{
if (m_queue->IsEmpty())
{
m_state = IDLE;
}
else
{
m_state = WAITING;
}
}
UpdateCredit(false);
}
2025-12-01 15:56:02 +01:00
void
Cbs::UpdateCredit(bool trigger_cb)
{
NS_LOG_FUNCTION(this);
NS_ASSERT_MSG(m_idleSlope < m_maxIdleSlope, "Trying to use an idleSlope higher than " << m_maxIdleSlope << ".");
Time sinceLastCreditUpdate = Simulator::Now() - m_lastUpdateCreditTime;
if(m_transmissionGateIsOpen){
if(m_state == WAITING)
{
m_credit = m_credit + sinceLastCreditUpdate.GetSeconds() * m_idleSlope.GetBitRate();
}
else if(m_state == IDLE)
{
double newCredit = m_credit + sinceLastCreditUpdate.GetSeconds() * m_idleSlope.GetBitRate();
if(newCredit>=0)
{
m_creditTrace(m_credit); //Hit the trace before reseting for nicer plot
m_credit = 0;
}
else if(newCredit<0)
{
m_credit = newCredit;
}
}
}
m_creditTrace(m_credit);
m_lastUpdateCreditTime = Simulator::Now();
if(m_credit < 0 && m_transmissionGateIsOpen){
Time nextUdpateDelay = Time(Seconds((-m_credit/m_idleSlope.GetBitRate())));
NS_LOG_INFO("Now " << m_lastUpdateCreditTime.GetNanoSeconds());
NS_LOG_INFO("Next update in " << nextUdpateDelay.GetNanoSeconds());
NS_LOG_INFO("Credit : " << m_credit << "\n");
if(Time::GetResolution()==Time::NS and nextUdpateDelay.GetNanoSeconds()==0)
{
//To solve infinit event schedule due to rounding error
nextUdpateDelay = Time(NanoSeconds(1));
}
else if(Time::GetResolution()==Time::PS and nextUdpateDelay.GetPicoSeconds()==0)
{
//To solve infinit event schedule due to rounding error
nextUdpateDelay = Time(PicoSeconds(1));
}
Simulator::Cancel(m_NextCreditUpdate);
m_NextCreditUpdate = Simulator::Schedule(nextUdpateDelay, &Cbs::UpdateCredit, this, true);
}
if(trigger_cb && m_credit >= 0 && m_state==WAITING)
{
NS_ASSERT_MSG (m_net != nullptr, "NetDevice not set in CBS. Use cbs->SetTsnNetDevice(net);");
if (!m_MultidropMode)
{
ReadyToTransmitCallback();
}
}
}
void
Cbs::TransmitStart(Ptr<Packet> p, Time txTime)
{
NS_LOG_FUNCTION(this);
m_state = TRANSMITTING;
UpdateCredit(true);
}
void
Cbs::TransmitComplete(Ptr<Packet> p)
{
NS_LOG_FUNCTION(this);
if (m_queue->IsEmpty()){
m_state = IDLE;
}
else{
m_state = WAITING;
}
int64_t sendSlope = m_idleSlope.GetBitRate() - m_portTransmitRate.GetBitRate();
Time sinceLastCreditUpdate = Simulator::Now() - m_lastUpdateCreditTime;
m_credit = m_credit + sendSlope*sinceLastCreditUpdate.GetSeconds();
m_lastUpdateCreditTime = Simulator::Now();
UpdateCredit(true);
}
void
Cbs::UpdateTransmissionGate(bool IsOpen)
{
NS_LOG_FUNCTION(this);
UpdateCredit(true);
m_transmissionGateIsOpen = IsOpen;
UpdateCredit(true);
if (not IsOpen)
{
Simulator::Cancel(m_NextCreditUpdate);
}
}
};