Files
eden-sim/contrib/tsn/model/frer-vector-recovery-function.cc

141 lines
4.8 KiB
C++

#include "frer-vector-recovery-function.h"
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "ns3/uinteger.h"
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("VectorRecoveryFunction");
NS_OBJECT_ENSURE_REGISTERED(VectorRecoveryFunction);
TypeId
VectorRecoveryFunction::GetTypeId()
{
static TypeId tid =
TypeId("ns3::VectorRecoveryFunction")
.SetParent<BaseRecoveryFunction>()
.SetGroupName("tsn")
.AddConstructor<VectorRecoveryFunction>()
.AddAttribute("HistoryLenght",
"Lenght of the history for the vector recovery algorithm",
UintegerValue(2),
MakeUintegerAccessor(&VectorRecoveryFunction::m_frerSeqRcvyHistoryLenght),
MakeUintegerChecker<uint>())
.AddAttribute("MaxHistoryLenght",
"Max Lenght of the history for the vector recovery algorithm",
UintegerValue(65535),
MakeUintegerAccessor(&VectorRecoveryFunction::m_maxFrerSeqRcvyHistoryLenght),
MakeUintegerChecker<uint16_t>());
return tid;
}
VectorRecoveryFunction::VectorRecoveryFunction()
{
NS_LOG_FUNCTION(this);
}
VectorRecoveryFunction::~VectorRecoveryFunction()
{
NS_LOG_FUNCTION(this);
}
bool
VectorRecoveryFunction::DoRecovery(uint16_t seqNumber)
{
NS_LOG_FUNCTION(this);
NS_ASSERT_MSG(m_frerSeqRcvyResetMSec <= m_frerMaxSeqRcvyResetMSec, "Trying to use a longer recovery reset timer than " << m_frerMaxSeqRcvyResetMSec << ".");
NS_ASSERT_MSG(m_frerSeqRcvyHistoryLenght <= m_maxFrerSeqRcvyHistoryLenght, "Trying to use a longer HistoryLenght than " << m_maxFrerSeqRcvyHistoryLenght << ".");
// Compute signed difference modulo RecovSeqSpace
int delta = (seqNumber-m_recovSeqNum) % m_recovSeqSpace;
if (0 != (delta & (m_recovSeqSpace/2)))
{
delta = delta - m_recovSeqSpace;
// Here, -(m_recovSeqSpace/2)<=delta<=((m_recovSeqSpace/2)-1)
}
// After reset, accept any packet
if(m_takeAny)
{
m_takeAny = false;
m_sequenceHistory.clear(); //Empty the vector in case of reset
m_sequenceHistory.insert(m_sequenceHistory.begin(), true); //Add a "seen" bool
for(int i = 0; i<m_frerSeqRcvyHistoryLenght-1; i++)
{
m_sequenceHistory.insert(m_sequenceHistory.end(), false); //Fill the others bool
}
m_recovSeqNum = seqNumber;
m_frerCpsSeqRcvyPassedPackets += 1;
Simulator::Cancel(m_resetEvent);
m_resetEvent = Simulator::Schedule(m_frerSeqRcvyResetMSec, &BaseRecoveryFunction::resetRecoveryFunction, this);
return true;
}
else if (delta > m_frerSeqRcvyHistoryLenght || delta <= -m_frerSeqRcvyHistoryLenght)
{
// Packet is out-of-range. Count and discard it.
m_frerCpsSeqRcvyRoguePackets += 1;
m_frerCpsSeqRcvyDiscardedPackets += 1;
if(m_frerSeqRcvyIndividualRecovery)
{
Simulator::Cancel(m_resetEvent);
m_resetEvent = Simulator::Schedule(m_frerSeqRcvyResetMSec, &BaseRecoveryFunction::resetRecoveryFunction, this);
}
return false;
}
else if (delta <= 0)
{
// Packet is old and in SequenceHistory; have we seen it before?
if (not m_sequenceHistory[-delta])
{
// Packet has not been seen. Take it.
m_sequenceHistory[-delta] = true;
m_frerCpsSeqRcvyOutOfOrderPackets += 1;
m_frerCpsSeqRcvyPassedPackets += 1;
Simulator::Cancel(m_resetEvent);
m_resetEvent = Simulator::Schedule(m_frerSeqRcvyResetMSec, &BaseRecoveryFunction::resetRecoveryFunction, this);
return true;
}
else
{
// Packet has been seen. Drop it.
m_frerCpsSeqRcvyDiscardedPackets += 1;
if(m_frerSeqRcvyIndividualRecovery)
{
Simulator::Cancel(m_resetEvent);
m_resetEvent = Simulator::Schedule(m_frerSeqRcvyResetMSec, &BaseRecoveryFunction::resetRecoveryFunction, this);
}
return false;
}
}
else
{
// Packet is not too far ahead of the one we want.
// Packet is out-of-order unless it directly follows RecovSeqNum
if (delta != 1)
{
m_frerCpsSeqRcvyOutOfOrderPackets += 1;
}
// Shift the history until bit 0 refers to sequence_number.
while (0 != (delta = delta - 1)){
m_sequenceHistory.insert(m_sequenceHistory.begin(), false);
}
m_sequenceHistory.insert(m_sequenceHistory.begin(), true);
m_sequenceHistory.resize(m_frerSeqRcvyHistoryLenght);
m_recovSeqNum = seqNumber;
m_frerCpsSeqRcvyPassedPackets += 1;
Simulator::Cancel(m_resetEvent);
m_resetEvent = Simulator::Schedule(m_frerSeqRcvyResetMSec, &BaseRecoveryFunction::resetRecoveryFunction, this);
return true;
}
return false;
}
}