Add NACK processing
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index 132ef36..397a5b0 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -175,6 +175,9 @@
*/
inline void
LeakBucket (const Time &interval);
+
+ inline void
+ LeakBucketByOnePacket ();
/**
* \brief Compare two faces. Only two faces on the same node could be compared.
@@ -252,6 +255,11 @@
m_bucket -= std::max (0.0, m_bucket-leak);
}
+void
+CcnxFace::LeakBucketByOnePacket ()
+{
+ m_bucket -= std::max (0.0, m_bucket-1.0);
+}
} // namespace ns3
diff --git a/model/ccnx-interest-header.h b/model/ccnx-interest-header.h
index d7be5fe..d93b42a 100644
--- a/model/ccnx-interest-header.h
+++ b/model/ccnx-interest-header.h
@@ -207,6 +207,7 @@
NORMAL_INTEREST = 0,
NACK_LOOP = 1,
NACK_CONGESTION,
+ NACK_GIVEUP_PIT,
};
void
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index e0e12c2..bba9ef9 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -287,58 +287,57 @@
}
void
-CcnxL3Protocol::OnNack (const Ptr<CcnxFace> &face,
+CcnxL3Protocol::OnNack (const Ptr<CcnxFace> &incomingFace,
Ptr<CcnxInterestHeader> &header,
- const Ptr<const Packet> &p)
+ const Ptr<const Packet> &packet)
{
- NS_LOG_FUNCTION (face << header << p);
+ NS_LOG_FUNCTION (incomingFace << header << packet);
- // Huh... Ignore all this for now
+ tuple<const CcnxPitEntry&,bool,bool> ret = m_pit->Lookup (*header);
+ CcnxPitEntry const& pitEntry = ret.get<0> ();
+ // bool isNew = ret.get<1> ();
+ bool isDuplicated = ret.get<2> ();
+
+ NS_ASSERT_MSG (isDuplicated,
+ "NACK should be a duplicated interest");
- /*if( header->IsCongested () == false )
- m_pit->LeakBucket(incomingFace,1);
-
-
- m_droppedInterestsTrace (header, DROP_CONGESTION,
- m_node->GetObject<Ccnx> (), incomingFace);
-
- m_pit->modify(pitEntry, CcnxPitEntry::DeleteOutgoing(incomingFace));*/
+ // CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry.m_incoming.find (incomingFace);
+ CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry.m_outgoing.find (incomingFace);
- // No matter is it duplicate or not, if it is a NACK message, remove all possible incoming
- // entries for this interface (NACK means that neighbor gave up trying and there is no
- // point of sending data in this direction)
+ NS_ASSERT_MSG (outFace != pitEntry.m_outgoing.end (),
+ "Outgoing entry should exist");
+
+ outFace->m_face->LeakBucketByOnePacket ();
+ // outFace->m_waitingInVain = true; // don't think that this is necessary
- // NS_LOG_INFO("Before (header->IsNack()) && (pitEntry != m_pit->end ())");
- // if ((header->IsNack()) && (pitEntry != m_pit->end ()))
- // {
- // //m_pit->erase (pitEntry);
- // NS_LOG_INFO("TRUE");
- // m_pit->modify(pitEntry, CcnxPitEntry::DeleteIncoming(incomingFace));
- // }
+ // m_droppedInterestsTrace (header, DROP_CONGESTION, m_node->GetObject<Ccnx> (), incomingFace);
- // m_fib->modify (m_fib->iterator_to (pitEntry->m_fibEntry),
- // CcnxFibEntry::UpdateStatus(incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
+ // If NACK is NACK_GIVEUP_PIT, then neighbor gave up trying to and removed it's PIT entry.
+ // So, if we had an incoming entry to this neighbor, then we can remove it now
- // if (!pitEntry.AreThereMoreFacesToTry ())
- // {
- // BOOST_FOREACH (const CcnxPitEntryIncomingFace face, pitEntry.m_incoming)
- // {
- // // check all entries if the name of RIT entry matches the name of interest
- // for (CcnxRitByNonce::type::iterator it = m_rit->begin(); it != m_rit->end(); it++)
- // {
- // if (it->m_prefix == iter->GetPrefix() )
- // {
- // header->SetNonce(it->m_nonce);
- // header->SetNack(true);
- // face.m_face->Send (packet->Copy());
- // }
- // }
- // }
+ if (header->GetNack () == CcnxInterestHeader::NACK_GIVEUP_PIT)
+ {
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind (&CcnxPitEntry::RemoveIncoming, ll::_1, incomingFace));
+ }
- // m_pit->erase(pitEntry);
+ m_fib->modify(m_fib->iterator_to (pitEntry.m_fibEntry),
+ ll::bind (&CcnxFibEntry::UpdateStatus,
+ ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
+
+ NS_ASSERT_MSG (m_forwardingStrategy != 0, "Need a forwarding protocol object to process packets");
- // return;
- // }
+ Ptr<Packet> nonNackInterest = Create<Packet> ();
+ header->SetNack (CcnxInterestHeader::NORMAL_INTEREST);
+ nonNackInterest->AddHeader (*header);
+
+ bool propagated = m_forwardingStrategy->
+ PropagateInterest (pitEntry, incomingFace, header, nonNackInterest);
+
+ // 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.
+ if (!propagated) GiveUpInterest (pitEntry, header);
}
// Processing Interests
@@ -454,30 +453,35 @@
// 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.
- if (!propagated)
- {
- Ptr<Packet> packet = Create<Packet> ();
- header->SetNack (CcnxInterestHeader::NACK_CONGESTION);
- packet->AddHeader (*header);
-
- BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
- {
- incoming.m_face->Send (packet->Copy ());
-
- // m_droppedInterestsTrace (header, DROP_CONGESTION,
- // m_node->GetObject<Ccnx> (), incomingFace);
- }
- // All incoming interests cannot be satisfied. Remove them
- m_pit->modify (m_pit->iterator_to (pitEntry),
- ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
-
- // Set pruning timout on PIT entry (instead of deleting the record)
- m_pit->modify (m_pit->iterator_to (pitEntry),
- ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
- Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
- }
+ if (!propagated) GiveUpInterest (pitEntry, header);
}
+void
+CcnxL3Protocol::GiveUpInterest (const CcnxPitEntry &pitEntry,
+ Ptr<CcnxInterestHeader> header)
+{
+ Ptr<Packet> packet = Create<Packet> ();
+ header->SetNack (CcnxInterestHeader::NACK_GIVEUP_PIT);
+ packet->AddHeader (*header);
+
+ BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
+ {
+ incoming.m_face->Send (packet->Copy ());
+
+ // m_droppedInterestsTrace (header, DROP_CONGESTION,
+ // m_node->GetObject<Ccnx> (), incomingFace);
+ }
+ // All incoming interests cannot be satisfied. Remove them
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
+
+ // Set pruning timout on PIT entry (instead of deleting the record)
+ m_pit->modify (m_pit->iterator_to (pitEntry),
+ ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
+ Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+}
+
+
// Processing ContentObjects
void
CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 272a0be..f5c19d9 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -219,7 +219,12 @@
GetBucketLeakInterval () const;
/// \brief Periodically generate pre-calculated number of tokens (leak buckets)
- void LeakBuckets( );
+ void
+ LeakBuckets ();
+
+ void
+ GiveUpInterest (const CcnxPitEntry &pitEntry,
+ Ptr<CcnxInterestHeader> header);
private:
uint32_t m_faceCounter; ///< \brief counter of faces. Increased every time a new face is added to the stack
diff --git a/model/ccnx-pit-entry-outgoing-face.cc b/model/ccnx-pit-entry-outgoing-face.cc
index ccdfb08..c15df71 100644
--- a/model/ccnx-pit-entry-outgoing-face.cc
+++ b/model/ccnx-pit-entry-outgoing-face.cc
@@ -27,7 +27,7 @@
CcnxPitEntryOutgoingFace::CcnxPitEntryOutgoingFace (Ptr<CcnxFace> face)
: m_face (face)
, m_sendTime (Simulator::Now ())
- , m_retxNum (0)
+ // , m_retxNum (0)
// , m_nonce (nonce)
// , m_outstanding (true)
// , m_waitingInVain (false)
diff --git a/model/ccnx-pit-entry-outgoing-face.h b/model/ccnx-pit-entry-outgoing-face.h
index 502f333..de1dd4b 100644
--- a/model/ccnx-pit-entry-outgoing-face.h
+++ b/model/ccnx-pit-entry-outgoing-face.h
@@ -38,10 +38,10 @@
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
+ // 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
- // bool m_waitingInVain; ///< \brief when flag is set, we do not expect data for this interest, only a small hope that it will happen
+ // 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);
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index a4db50a..61b4fcc 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -49,6 +49,13 @@
return ret.first;
}
+void
+CcnxPitEntry::RemoveIncoming (Ptr<CcnxFace> face)
+{
+ m_incoming.erase (face);
+}
+
+
CcnxPitEntryOutgoingFaceContainer::type::iterator
CcnxPitEntry::AddOutgoing (Ptr<CcnxFace> face)
{
diff --git a/model/ccnx-pit-entry.h b/model/ccnx-pit-entry.h
index 9f05e1e..bb42a6a 100644
--- a/model/ccnx-pit-entry.h
+++ b/model/ccnx-pit-entry.h
@@ -164,6 +164,12 @@
AddIncoming (Ptr<CcnxFace> face);
/**
+ * @brief Remove incoming entry for face `face`
+ */
+ void
+ RemoveIncoming (Ptr<CcnxFace> face);
+
+ /**
* @brief Clear all incoming faces either after all of them were satisfied or NACKed
*/
void