193 lines
5.0 KiB
C++
193 lines
5.0 KiB
C++
#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;
|
|
}
|
|
}
|
|
|
|
void
|
|
Cbs::Update()
|
|
{
|
|
NS_LOG_FUNCTION(this);
|
|
if (m_state != TRANSMITTING)
|
|
{
|
|
if (m_queue->IsEmpty())
|
|
{
|
|
m_state = IDLE;
|
|
}
|
|
else
|
|
{
|
|
m_state = WAITING;
|
|
}
|
|
}
|
|
UpdateCredit(false);
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
};
|