Several fixes in forwarding strategies and NACK processing
- All strategies will forward to one green face first, if it exists
- Implemented logic to detect retransmitted interests (same face)
- If interest is retransmitted and all faces are exhausted during the
propagation face, increase max retx counter and try again
- PIT entry lifetime is updated on every non-duplicate interest reception
diff --git a/model/ccnx-bestroute-strategy.cc b/model/ccnx-bestroute-strategy.cc
index ab525b5..b850d08 100644
--- a/model/ccnx-bestroute-strategy.cc
+++ b/model/ccnx-bestroute-strategy.cc
@@ -32,7 +32,9 @@
namespace ns3
{
-
+
+using namespace __ccnx_private;
+
NS_OBJECT_ENSURE_REGISTERED (CcnxBestRouteStrategy);
TypeId CcnxBestRouteStrategy::GetTypeId (void)
@@ -56,43 +58,51 @@
const Ptr<const Packet> &packet)
{
NS_LOG_FUNCTION (this);
- bool forwardedCount = 0;
- try
+ // Try to work out with just green faces
+ bool greenOk = PropagateInterestViaGreen (pitEntry, incomingFace, header, packet);
+ if (greenOk)
+ return true;
+
+ int propagatedCount = 0;
+
+ BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
{
- for (uint32_t skip = 0; skip < pitEntry.m_fibEntry.m_faces.size (); skip++)
+ if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED) // all non-read faces are in front
+ break;
+
+ if (metricFace.m_face == incomingFace)
+ continue; // same face as incoming, don't forward
+
+ if (pitEntry.m_incoming.find (metricFace.m_face) != pitEntry.m_incoming.end ())
+ continue; // don't forward to face that we received interest from
+
+ CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
+ pitEntry.m_outgoing.find (metricFace.m_face);
+
+ if (outgoing != pitEntry.m_outgoing.end () &&
+ outgoing->m_retxCount >= pitEntry.m_maxRetxCount)
{
- const CcnxFibFaceMetric bestMetric = pitEntry.m_fibEntry.FindBestCandidate (skip);
-
- if (bestMetric.m_status == CcnxFibFaceMetric::NDN_FIB_RED) // no point to send there
- continue;
-
- if (pitEntry.m_incoming.find (bestMetric.m_face) != pitEntry.m_incoming.end ())
- continue; // don't forward to face that we received interest from
-
- if (pitEntry.m_outgoing.find (bestMetric.m_face) != pitEntry.m_outgoing.end ()) // already forwarded before
- continue;
-
- bool faceAvailable = bestMetric.m_face->IsBelowLimit ();
- if (!faceAvailable) // huh...
- continue;
-
- m_pit->modify (m_pit->iterator_to (pitEntry),
- ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, bestMetric.m_face));
-
- // NS_LOG_DEBUG ("new outgoing entry for " << boost::cref (*metricFace.m_face));
-
- bestMetric.m_face->Send (packet->Copy ());
-
- forwardedCount++;
- break; // if we succeeded in sending one packet, stop
+ continue; // already forwarded before during this retransmission cycle
}
- }
- catch (CcnxFibEntry::NoFaces)
- {
+
+ bool faceAvailable = metricFace.m_face->IsBelowLimit ();
+ if (!faceAvailable) // huh...
+ {
+ continue;
+ }
+
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
+
+ metricFace.m_face->Send (packet->Copy ());
+
+ propagatedCount++;
+ break; // do only once
}
- return forwardedCount > 0;
+ NS_LOG_INFO ("Propagated to " << propagatedCount << " faces");
+ return propagatedCount > 0;
}
} //namespace ns3
diff --git a/model/ccnx-flooding-strategy.cc b/model/ccnx-flooding-strategy.cc
index 94c6512..f2add5f 100644
--- a/model/ccnx-flooding-strategy.cc
+++ b/model/ccnx-flooding-strategy.cc
@@ -34,7 +34,9 @@
namespace ns3
{
-
+
+using namespace __ccnx_private;
+
NS_OBJECT_ENSURE_REGISTERED (CcnxFloodingStrategy);
TypeId CcnxFloodingStrategy::GetTypeId (void)
@@ -58,9 +60,17 @@
const Ptr<const Packet> &packet)
{
NS_LOG_FUNCTION (this);
-
+
+ // Try to work out with just green faces
+ bool greenOk = PropagateInterestViaGreen (pitEntry, incomingFace, header, packet);
+ if (greenOk)
+ return true;
+
+ // boo... :(
+
int propagatedCount = 0;
- BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces)
+
+ BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
{
if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED) // all non-read faces are in front
break;
@@ -70,14 +80,19 @@
if (pitEntry.m_incoming.find (metricFace.m_face) != pitEntry.m_incoming.end ())
continue; // don't forward to face that we received interest from
+
+ CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
+ pitEntry.m_outgoing.find (metricFace.m_face);
- if (pitEntry.m_outgoing.find (metricFace.m_face) != pitEntry.m_outgoing.end ())
- continue; // already forwarded before
+ if (outgoing != pitEntry.m_outgoing.end () &&
+ outgoing->m_retxCount >= pitEntry.m_maxRetxCount)
+ {
+ continue; // already forwarded before during this retransmission cycle
+ }
bool faceAvailable = metricFace.m_face->IsBelowLimit ();
if (!faceAvailable) // huh...
{
- // NS_LOG_ERROR (boost::cref (*metricFace.m_face) << " limit !!!");
continue;
}
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 40b9e47..869e424 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -21,8 +21,18 @@
#include "ns3/assert.h"
-#include "ccnx-route.h"
#include "ccnx-forwarding-strategy.h"
+#include "ns3/log.h"
+#include "ns3/simulator.h"
+#include "ccnx-interest-header.h"
+
+#include <boost/ref.hpp>
+#include <boost/foreach.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
+
+NS_LOG_COMPONENT_DEFINE ("CcnxForwardingStrategy");
namespace ns3 {
@@ -50,11 +60,53 @@
{
m_pit = pit;
}
-
-// Ptr<CcnxPit>
-// CcnxForwardingStrategy::GetPit ()
-// {
-// return m_pit;
-// }
-
+
+bool
+CcnxForwardingStrategy::PropagateInterestViaGreen (const CcnxPitEntry &pitEntry,
+ const Ptr<CcnxFace> &incomingFace,
+ Ptr<CcnxInterestHeader> &header,
+ const Ptr<const Packet> &packet)
+{
+ NS_LOG_FUNCTION (this);
+
+ int propagatedCount = 0;
+
+ BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces)
+ {
+ if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED ||
+ metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_YELLOW)
+ break; //propagate only to green faces
+
+ if (pitEntry.m_incoming.find (metricFace.m_face) != pitEntry.m_incoming.end ())
+ continue; // don't forward to face that we received interest from
+
+ CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
+ pitEntry.m_outgoing.find (metricFace.m_face);
+
+ if (outgoing != pitEntry.m_outgoing.end () &&
+ outgoing->m_retxCount >= pitEntry.m_maxRetxCount)
+ {
+ continue;
+ }
+
+ bool faceAvailable = metricFace.m_face->IsBelowLimit ();
+ if (!faceAvailable) // huh...
+ {
+ // let's try different green face
+ continue;
+ }
+
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind(&CcnxPitEntry::AddOutgoing, ll::_1, metricFace.m_face));
+
+ metricFace.m_face->Send (packet->Copy ());
+
+ propagatedCount++;
+ break; // propagate only one interest
+ }
+
+ return propagatedCount > 0;
+}
+
+
} //namespace ns3
diff --git a/model/ccnx-forwarding-strategy.h b/model/ccnx-forwarding-strategy.h
index d7a5ab5..aff0909 100644
--- a/model/ccnx-forwarding-strategy.h
+++ b/model/ccnx-forwarding-strategy.h
@@ -51,7 +51,7 @@
virtual ~CcnxForwardingStrategy ();
/**
- * @brief Interface method to propagate the insterest according to the forwarding strategy
+ * @brief Base method to propagate the insterest according to the forwarding strategy
*
* @param pitEntry Reference to PIT entry (reference to corresponding FIB entry inside)
* @param incomingFace Incoming face
@@ -65,7 +65,7 @@
PropagateInterest (const CcnxPitEntry &pitEntry,
const Ptr<CcnxFace> &incomingFace,
Ptr<CcnxInterestHeader> &header,
- const Ptr<const Packet> &packe) = 0;
+ const Ptr<const Packet> &packet) = 0;
/**
* @brief Set link to PIT for the forwarding strategy
@@ -75,6 +75,25 @@
void
SetPit (Ptr<CcnxPit> pit);
+protected:
+ /**
+ * @brief Propage interest vie a green interface. Fail, if no green interfaces available
+ *
+ * @param pitEntry Reference to PIT entry (reference to corresponding FIB entry inside)
+ * @param incomingFace Incoming face
+ * @param header CcnxInterestHeader
+ * @param packet Original Interest packet
+ * @param sendCallback Send callback
+ * @return true if interest was successfully propagated, false if all options have failed
+ *
+ * \see PropagateInterest
+ */
+ bool
+ PropagateInterestViaGreen (const CcnxPitEntry &pitEntry,
+ const Ptr<CcnxFace> &incomingFace,
+ Ptr<CcnxInterestHeader> &header,
+ const Ptr<const Packet> &packet);
+
protected:
Ptr<CcnxPit> m_pit;
};
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index 596b36a..7fb9aab 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -319,8 +319,10 @@
return;
}
- NS_ASSERT_MSG (incomingFace == outFace->m_face, "Something is wrong");
- incomingFace->LeakBucketByOnePacket ();
+ // This was done in error. Never, never do anything, except normal leakage. This way we ensure that we will not have losses,
+ // at least when there is only one client
+ //
+ // incomingFace->LeakBucketByOnePacket ();
m_pit->modify (m_pit->iterator_to (pitEntry),
ll::bind (&CcnxPitEntry::SetWaitingInVain, ll::_1, outFace));
@@ -336,9 +338,9 @@
ll::bind (&CcnxPitEntry::RemoveIncoming, ll::_1, incomingFace));
}
- m_fib->modify(m_fib->iterator_to (pitEntry.m_fibEntry),
- ll::bind (&CcnxFibEntry::UpdateStatus,
- ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
+ m_fib->modify (m_fib->iterator_to (pitEntry.m_fibEntry),
+ ll::bind (&CcnxFibEntry::UpdateStatus,
+ ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
if (!pitEntry.AreAllOutgoingInVain ()) // not all ougtoing are in vain
{
@@ -428,10 +430,13 @@
CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry.m_incoming.find (incomingFace);
CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry.m_outgoing.find (incomingFace);
+ bool isRetransmitted = false;
+
if (inFace != pitEntry.m_incoming.end ())
{
// CcnxPitEntryIncomingFace.m_arrivalTime keeps track arrival time of the first packet... why?
-
+
+ isRetransmitted = true;
// this is almost definitely a retransmission. But should we trust the user on that?
}
else
@@ -440,6 +445,11 @@
ll::var(inFace) = ll::bind (&CcnxPitEntry::AddIncoming, ll::_1, incomingFace));
}
+ // update PIT entry lifetime
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind (&CcnxPitEntry::UpdateLifetime, ll::_1,
+ header->GetInterestLifetime ()));
+
if (outFace != pitEntry.m_outgoing.end ())
{
// got a non-duplicate interest from the face we have sent interest to
@@ -455,7 +465,8 @@
ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
}
- if (pitEntry.AreTherePromisingOutgoingFacesExcept (incomingFace))
+ if (!isRetransmitted &&
+ pitEntry.AreTherePromisingOutgoingFacesExcept (incomingFace))
{ // Suppress this interest if we're still expecting data from some other face
// We are already expecting data later in future. Suppress the interest
@@ -472,6 +483,17 @@
bool propagated = m_forwardingStrategy->
PropagateInterest (pitEntry, incomingFace, header, packet);
+ if (isRetransmitted) //give another chance if retransmitted
+ {
+ // increase max number of allowed retransmissions
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind (&CcnxPitEntry::IncreaseAllowedRetxCount, ll::_1));
+
+ // try again
+ propagated = m_forwardingStrategy->
+ PropagateInterest (pitEntry, incomingFace, header, packet);
+ }
+
// ForwardingStrategy will try its best to forward packet to at least one interface.
// If no interests was propagated, then there is not other option for forwarding or
// ForwardingStrategy failed to find it.
diff --git a/model/ccnx-pit-entry-outgoing-face.cc b/model/ccnx-pit-entry-outgoing-face.cc
index a0a8772..8527779 100644
--- a/model/ccnx-pit-entry-outgoing-face.cc
+++ b/model/ccnx-pit-entry-outgoing-face.cc
@@ -27,11 +27,17 @@
CcnxPitEntryOutgoingFace::CcnxPitEntryOutgoingFace (Ptr<CcnxFace> face)
: m_face (face)
, m_sendTime (Simulator::Now ())
- // , m_retxNum (0)
- // , m_nonce (nonce)
- // , m_outstanding (true)
+ , m_retxCount (0)
, m_waitingInVain (false)
{
}
+void
+CcnxPitEntryOutgoingFace::UpdateOnRetransmit ()
+{
+ m_sendTime = Simulator::Now ();
+ m_retxCount++;
+ m_waitingInVain = false;
+}
+
} // namespace ns3
diff --git a/model/ccnx-pit-entry-outgoing-face.h b/model/ccnx-pit-entry-outgoing-face.h
index 0fce545..c0fe80f 100644
--- a/model/ccnx-pit-entry-outgoing-face.h
+++ b/model/ccnx-pit-entry-outgoing-face.h
@@ -38,14 +38,18 @@
Time m_sendTime; ///< \brief time when the first outgoing interest is sent (for RTT measurements)
///< \todo handle problem of retransmitted interests... Probably, we should include something similar
///< to TimeStamp TCP option for retransmitted (i.e., only lost interests will suffer)
- // uint32_t m_retxNum; ///< \brief number of retransmission
- // int m_nonce; ///< \brief nonce of the outgoing Interest
- // bool m_outstanding; ///< \brief flag to indicate that this interest is currently pending
+ uint32_t m_retxCount; ///< \brief number of retransmission
bool m_waitingInVain; ///< \brief when flag is set, we do not expect data for this interest, only a small hope that it will happen
public:
CcnxPitEntryOutgoingFace (Ptr<CcnxFace> face);
+ /**
+ * @brief Update outgoing entry upon retransmission
+ */
+ void
+ UpdateOnRetransmit ();
+
bool operator== (const CcnxPitEntryOutgoingFace &dst) { return *m_face==*dst.m_face; }
bool operator== (Ptr<CcnxFace> face) { return *m_face==*face; }
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index 348f01b..5667c82 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -26,6 +26,7 @@
#include "ns3/log.h"
#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
namespace ll = boost::lambda;
NS_LOG_COMPONENT_DEFINE ("CcnxPitEntry");
@@ -38,12 +39,21 @@
const CcnxFibEntry &fibEntry)
: m_prefix (prefix)
, m_fibEntry (fibEntry)
- , m_expireTime (expireTime)
- , m_timerExpired (false)
- , m_counterExpirations (0)
+ , m_expireTime (Simulator::Now () + expireTime)
+ // , m_timerExpired (false)
+ // , m_counterExpirations (0)
+ , m_maxRetxCount (0)
{
}
+void
+CcnxPitEntry::UpdateLifetime (const Time &offsetTime)
+{
+ Time newExpireTime = Simulator::Now () + offsetTime;
+ if (newExpireTime > m_expireTime)
+ m_expireTime = newExpireTime;
+}
+
CcnxPitEntryIncomingFaceContainer::type::iterator
CcnxPitEntry::AddIncoming (Ptr<CcnxFace> face)
{
@@ -68,7 +78,11 @@
std::pair<CcnxPitEntryOutgoingFaceContainer::type::iterator,bool> ret =
m_outgoing.insert (CcnxPitEntryOutgoingFace (face));
- NS_ASSERT_MSG (ret.second, "Something is wrong");
+ if (!ret.second)
+ { // outgoing face already exists
+ m_outgoing.modify (ret.first,
+ ll::bind (&CcnxPitEntryOutgoingFace::UpdateOnRetransmit, ll::_1));
+ }
return ret.first;
}
@@ -119,4 +133,10 @@
return !inVain;
}
+void
+CcnxPitEntry::IncreaseAllowedRetxCount ()
+{
+ m_maxRetxCount++;
+}
+
}
diff --git a/model/ccnx-pit-entry.h b/model/ccnx-pit-entry.h
index 93e4869..162d7a5 100644
--- a/model/ccnx-pit-entry.h
+++ b/model/ccnx-pit-entry.h
@@ -45,7 +45,7 @@
namespace __ccnx_private
{
-// class i_face {};
+class i_retx {};
}
/**
@@ -85,7 +85,11 @@
boost::multi_index::ordered_unique<
boost::multi_index::tag<__ccnx_private::i_face>,
boost::multi_index::member<CcnxPitEntryOutgoingFace, Ptr<CcnxFace>, &CcnxPitEntryOutgoingFace::m_face>
- >
+ >,
+ boost::multi_index::ordered_non_unique<
+ boost::multi_index::tag<__ccnx_private::i_retx>,
+ boost::multi_index::member<CcnxPitEntryOutgoingFace, uint32_t, &CcnxPitEntryOutgoingFace::m_retxCount>
+ >
>
> type;
};
@@ -101,18 +105,25 @@
/**
* \brief PIT entry constructor
* \param prefix Prefix of the PIT entry
+ * \param offsetTime Relative time to the current moment, representing PIT entry lifetime
* \param fibEntry A FIB entry associated with the PIT entry
*/
- CcnxPitEntry (Ptr<CcnxNameComponents> prefix, const Time &expireTime, const CcnxFibEntry &fibEntry);
+ CcnxPitEntry (Ptr<CcnxNameComponents> prefix, const Time &offsetTime, const CcnxFibEntry &fibEntry);
- // // Get number of outgoing interests that we're expecting data from
- // inline size_t numberOfPromisingInterests( ) const;
-
+ /**
+ * @brief Update lifetime of PIT entry
+ *
+ * This function will update PIT entry lifetime to the maximum of the current lifetime and
+ * the lifetime Simulator::Now () + offsetTime
+ *
+ * @param offsetTime Relative time to the current moment, representing PIT entry lifetime
+ */
+ void
+ UpdateLifetime (const Time &offsetTime);
+
const CcnxNameComponents &
GetPrefix () const
- {
- return *m_prefix;
- }
+ { return *m_prefix; }
/**
* @brief Get current expiration time of the record
@@ -130,9 +141,7 @@
*/
void
SetExpireTime (const Time &expireTime)
- {
- m_expireTime = expireTime;
- }
+ { m_expireTime = expireTime; }
/**
* @brief Check if nonce `nonce` for the same prefix has already been seen
@@ -212,6 +221,12 @@
**/
bool
AreTherePromisingOutgoingFacesExcept (Ptr<CcnxFace> face) const;
+
+ /**
+ * @brief Increase maximum limit of allowed retransmission per outgoing face
+ */
+ void
+ IncreaseAllowedRetxCount ();
protected:
@@ -227,8 +242,8 @@
CcnxPitEntryOutgoingFaceContainer::type m_outgoing; ///< \brief container for outgoing interests
Time m_expireTime; ///< \brief Time when PIT entry will be removed
- bool m_timerExpired; ///< \brief flag indicating that PIT timer has expired
- int m_counterExpirations; ///< \brief whether timer is expired (+ number of times timer expired)
+
+ uint32_t m_maxRetxCount; ///< @brief Maximum allowed number of retransmissions via outgoing faces
};
} // namespace ns3
diff --git a/model/ccnx-pit.cc b/model/ccnx-pit.cc
index 9770bd0..1cfa3f9 100644
--- a/model/ccnx-pit.cc
+++ b/model/ccnx-pit.cc
@@ -171,9 +171,8 @@
entry = insert (end (),
CcnxPitEntry (Create<CcnxNameComponents> (header.GetName ()),
- Simulator::Now () +
- (header.GetInterestLifetime ().IsZero ()?m_PitEntryDefaultLifetime
- : header.GetInterestLifetime ()),
+ header.GetInterestLifetime ().IsZero ()?m_PitEntryDefaultLifetime
+ : header.GetInterestLifetime (),
*fibEntry));
// isDuplicate = false; // redundant