#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() .SetGroupName("tsn") .AddConstructor() .AddAttribute("HistoryLenght", "Lenght of the history for the vector recovery algorithm", UintegerValue(2), MakeUintegerAccessor(&VectorRecoveryFunction::m_frerSeqRcvyHistoryLenght), MakeUintegerChecker()) .AddAttribute("MaxHistoryLenght", "Max Lenght of the history for the vector recovery algorithm", UintegerValue(65535), MakeUintegerAccessor(&VectorRecoveryFunction::m_maxFrerSeqRcvyHistoryLenght), MakeUintegerChecker()); 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 || 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; } }