Checkpoint. Basic support (and not real success) for interest limits
diff --git a/model/fw/per-fib-limits.cc b/model/fw/per-fib-limits.cc
index 89d4cc4..5c2d3a2 100644
--- a/model/fw/per-fib-limits.cc
+++ b/model/fw/per-fib-limits.cc
@@ -20,6 +20,7 @@
#include "per-fib-limits.h"
+#include "ns3/ndn-l3-protocol.h"
#include "ns3/ndn-interest-header.h"
#include "ns3/ndn-content-object-header.h"
#include "ns3/ndn-pit.h"
@@ -32,6 +33,7 @@
#include "ns3/double.h"
#include <boost/foreach.hpp>
+#include <boost/lexical_cast.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
namespace ll = boost::lambda;
@@ -62,10 +64,24 @@
void
PerFibLimits::DoDispose ()
{
+ m_announceEvent.Cancel ();
+
super::DoDispose ();
}
void
+PerFibLimits::NotifyNewAggregate ()
+{
+ super::NotifyNewAggregate ();
+
+ if (m_pit != 0 && m_fib != 0)
+ {
+ m_announceEvent = Simulator::Schedule (Seconds (1.0),
+ &PerFibLimits::AnnounceLimits, this);
+ }
+}
+
+void
PerFibLimits::RemoveFace (Ptr<Face> face)
{
for (PitQueueMap::iterator item = m_pitQueues.begin ();
@@ -79,6 +95,16 @@
super::RemoveFace (face);
}
+void
+PerFibLimits::OnInterest (Ptr<Face> face,
+ Ptr<const InterestHeader> header,
+ Ptr<const Packet> origPacket)
+{
+ if (header->GetScope () != 0)
+ super::OnInterest (face, header, origPacket);
+ else
+ ApplyAnnouncedLimit (face, header);
+}
bool
PerFibLimits::TrySendOutInterest (Ptr<Face> inFace,
@@ -137,21 +163,10 @@
pitEntry->UpdateLifetime (Seconds (0.10));
// const ndnSIM::LoadStatsFace &stats = GetStatsTree ()[header->GetName ()].incoming ().find (inFace)->second;
- const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
- double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
- // if (weight < 0)
- // {
- // // if stats is unknown, gracefully accept interest with normal priority
- // weight = 1.0;
- // }
-
- bool enqueued = m_pitQueues[outFace].Enqueue (inFace, pitEntry, weight);
+ // const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
+ // double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
+ bool enqueued = m_pitQueues[outFace].Enqueue (inFace, pitEntry, 1);
- // if (Simulator::GetContext () == 6)
- // {
- // // std::cerr << "Attempt to enqueue packet for " << pitEntry->GetPrefix () << ": " << (enqueued?"succeeded":"failed") << std::endl;
- // }
-
if (enqueued)
{
NS_LOG_DEBUG ("PIT entry is enqueued for delayed processing. Telling that we forwarding possible");
@@ -280,36 +295,138 @@
uint32_t nackCode,
Ptr<pit::Entry> pitEntry)
{
- super::DidReceiveValidNack (inFace, nackCode, pitEntry);
+// super::DidReceiveValidNack (inFace, nackCode, pitEntry);
- // NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
- PitQueue::Remove (pitEntry);
+// // NS_LOG_FUNCTION (this << pitEntry->GetPrefix ());
+// PitQueue::Remove (pitEntry);
- Ptr<InterestHeader> nackHeader = Create<InterestHeader> (*pitEntry->GetInterest ());
- // nackHeader->SetNack (100);
- Ptr<Packet> pkt = Create<Packet> ();
- pkt->AddHeader (*nackHeader);
+// Ptr<InterestHeader> nackHeader = Create<InterestHeader> (*pitEntry->GetInterest ());
+// // nackHeader->SetNack (100);
+// Ptr<Packet> pkt = Create<Packet> ();
+// pkt->AddHeader (*nackHeader);
- for (pit::Entry::in_container::iterator face = pitEntry->GetIncoming ().begin ();
- face != pitEntry->GetIncoming ().end ();
- face ++)
- {
- face->m_face->Send (pkt->Copy ());
- }
+// for (pit::Entry::in_container::iterator face = pitEntry->GetIncoming ().begin ();
+// face != pitEntry->GetIncoming ().end ();
+// face ++)
+// {
+// face->m_face->Send (pkt->Copy ());
+// }
- for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
- face != pitEntry->GetOutgoing ().end ();
- face ++)
+// for (pit::Entry::out_container::iterator face = pitEntry->GetOutgoing ().begin ();
+// face != pitEntry->GetOutgoing ().end ();
+// face ++)
+// {
+// face->m_face->GetLimits ().RemoveOutstanding ();
+// }
+
+// m_pit->MarkErased (pitEntry);
+
+// ProcessFromQueue ();
+}
+
+void
+PerFibLimits::AnnounceLimits ()
+{
+ Ptr<L3Protocol> l3 = GetObject<L3Protocol> ();
+ NS_ASSERT (l3 != 0);
+
+ if (l3->GetNFaces () < 2)
{
- face->m_face->GetLimits ().RemoveOutstanding ();
+ m_announceEvent = Simulator::Schedule (Seconds (1.0),
+ &PerFibLimits::AnnounceLimits, this);
+ return;
+ }
+
+ double sumOfWeights = 0;
+ double weightNormalization = 1.0;
+ for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
+ {
+ Ptr<Face> inFace = l3->GetFace (faceId);
+
+ const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
+ double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
+ if (weight < 0) weight = 0.5;
+
+ sumOfWeights += weight;
+ }
+ if (sumOfWeights >= 1)
+ {
+ // disable normalization (not necessary)
+ weightNormalization = 1.0;
+ }
+ else
+ {
+ // sumOfWeights /= (l3->GetNFaces ());
+ weightNormalization = 1 / sumOfWeights;
}
- m_pit->MarkErased (pitEntry);
+ for (Ptr<fib::Entry> entry = m_fib->Begin ();
+ entry != m_fib->End ();
+ entry = m_fib->Next (entry))
+ {
+ InterestHeader announceInterest;
+ announceInterest.SetScope (0); // link-local
+
+ uint32_t totalAllowance = 0;
+ for (fib::FaceMetricContainer::type::iterator fibFace = entry->m_faces.begin ();
+ fibFace != entry->m_faces.end ();
+ fibFace ++)
+ {
+ totalAllowance += fibFace->m_face->GetLimits ().GetMaxLimit ();
+ }
+
+ if (totalAllowance == 0)
+ {
+ // don't announce anything, there is no limit
+ continue;
+ }
+
+ for (uint32_t faceId = 0; faceId < l3->GetNFaces (); faceId ++)
+ {
+ Ptr<Face> inFace = l3->GetFace (faceId);
+
+ const ndnSIM::LoadStatsFace &stats = GetStatsTree ()["/"].incoming ().find (inFace)->second;
+ double weight = std::min (1.0, stats.GetSatisfiedRatio ().get<0> ());
+ if (weight < 0) weight = 0.5;
+
+ Ptr<NameComponents> prefixWithLimit = Create<NameComponents> (entry->GetPrefix ());
+ (*prefixWithLimit)
+ ("limit")
+ (static_cast<uint32_t> (std::max (1.0, weightNormalization * weight * totalAllowance)));
+
+ announceInterest.SetName (prefixWithLimit);
+ // lifetime is 0
+
+ Ptr<Packet> pkt = Create<Packet> ();
+ pkt->AddHeader (announceInterest);
+
+ inFace->Send (pkt);
+ }
+ }
+
+ m_announceEvent = Simulator::Schedule (Seconds (1.0),
+ &PerFibLimits::AnnounceLimits, this);
+}
+
+void
+PerFibLimits::ApplyAnnouncedLimit (Ptr<Face> inFace,
+ Ptr<const InterestHeader> header)
+{
+ // Ptr<fib::Entry> fibEntry = m_fib->LongestPrefixMatch (header);
+ // if (fibEntry == 0)
+ // return;
+
+ uint32_t limit = boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ());
+ inFace->GetLimits ().SetMaxLimit (limit);
- ProcessFromQueue ();
+ // if (Simulator::GetContext () == 6 || Simulator::GetContext () == 4)
+ // {
+ // std::cerr << Simulator::Now ().ToDouble (Time::S) << "s from:" << *inFace << " " << *header << std::endl;
+ // std::cerr << header->GetName ().GetLastComponent () << ", " << boost::lexical_cast<uint32_t> (header->GetName ().GetLastComponent ()) << std::endl;
+ // }
}
diff --git a/model/fw/per-fib-limits.h b/model/fw/per-fib-limits.h
index 298c9ee..4088ae2 100644
--- a/model/fw/per-fib-limits.h
+++ b/model/fw/per-fib-limits.h
@@ -51,6 +51,11 @@
PerFibLimits ();
virtual void
+ OnInterest (Ptr<Face> face,
+ Ptr<const InterestHeader> header,
+ Ptr<const Packet> origPacket);
+
+ virtual void
WillEraseTimedOutPendingInterest (Ptr<pit::Entry> pitEntry);
virtual void
@@ -76,14 +81,26 @@
private:
void
ProcessFromQueue ();
+
+ void
+ AnnounceLimits ();
+
+ void
+ ApplyAnnouncedLimit (Ptr<Face> inFace,
+ Ptr<const InterestHeader> header);
// from Object
- void
+ virtual void
+ NotifyNewAggregate (); ///< @brief Even when object is aggregated to another Object
+
+ virtual void
DoDispose ();
private:
typedef std::map< Ptr<Face>, PitQueue > PitQueueMap;
PitQueueMap m_pitQueues; // per-outgoing face pit queue
+
+ EventId m_announceEvent;
};