141 lines
4.8 KiB
C++
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;
|
|
}
|
|
|
|
}
|