NDN layer now knows how to process ContentObject packets
diff --git a/apps/ccnx-producer.cc b/apps/ccnx-producer.cc
index 24126b9..43964b1 100644
--- a/apps/ccnx-producer.cc
+++ b/apps/ccnx-producer.cc
@@ -186,6 +186,6 @@
void
CcnxProducer::AddContentStoreEntry (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet)
{
- m_ccnx->m_contentStore->Add (header, packet);
+ // m_ccnx->m_contentStore->Add (header, packet);
}
}
diff --git a/helper/ccnx-stack-helper.h b/helper/ccnx-stack-helper.h
index 7308241..060b0a7 100644
--- a/helper/ccnx-stack-helper.h
+++ b/helper/ccnx-stack-helper.h
@@ -58,7 +58,7 @@
{
public:
/**
- * \brief Create a new CcnxStackHelper which <empty> forwarding by default.
+ * \brief Create a new CcnxStackHelper with empty forwarding by default.
*
* \todo set non-empty default forwarding
*/
diff --git a/model/ccnx-content-store.cc b/model/ccnx-content-store.cc
index c47159e..1a27969 100644
--- a/model/ccnx-content-store.cc
+++ b/model/ccnx-content-store.cc
@@ -31,27 +31,27 @@
namespace ns3
{
-NS_OBJECT_ENSURE_REGISTERED (CcnxContentStore);
+// NS_OBJECT_ENSURE_REGISTERED (CcnxContentStore);
-using namespace __ccnx_private_content_store;
+using namespace __ccnx_private;
-TypeId
-CcnxContentStore::GetTypeId (void)
-{
- static TypeId tid = TypeId ("ns3::CcnxContentStore")
- .SetGroupName ("Ccnx")
- .SetParent<Object> ()
- .AddConstructor<CcnxContentStore> ()
- .AddAttribute ("Size",
- "Maximum number of packets that content storage can hold",
- UintegerValue (100),
- MakeUintegerAccessor (&CcnxContentStore::SetMaxSize,
- &CcnxContentStore::GetMaxSize),
- MakeUintegerChecker<uint32_t> ())
- ;
+// TypeId
+// CcnxContentStore::GetTypeId (void)
+// {
+// static TypeId tid = TypeId ("ns3::CcnxContentStore")
+// .SetGroupName ("Ccnx")
+// .SetParent<Object> ()
+// .AddConstructor<CcnxContentStore> ()
+// .AddAttribute ("Size",
+// "Maximum number of packets that content storage can hold",
+// UintegerValue (100),
+// MakeUintegerAccessor (&CcnxContentStore::SetMaxSize,
+// &CcnxContentStore::GetMaxSize),
+// MakeUintegerChecker<uint32_t> ())
+// ;
- return tid;
-}
+// return tid;
+// }
CcnxContentObjectTail CcnxContentStoreEntry::m_tail;
@@ -65,7 +65,7 @@
struct CcnxContentStoreByPrefix
{
typedef
- CcnxContentStoreContainer::type::index<hash>::type
+ CcnxContentStoreContainer::type::index<i_prefix>::type
type;
};
@@ -76,12 +76,12 @@
struct CcnxContentStoreByMru
{
typedef
- CcnxContentStoreContainer::type::index<mru>::type
+ CcnxContentStoreContainer::type::index<i_mru>::type
type;
};
#ifdef _DEBUG
-#define DUMP_INDEX_TAG ordered
+#define DUMP_INDEX_TAG i_ordered
#define DUMP_INDEX CcnxContentStoreOrderedPrefix
/**
* \ingroup ccnx
@@ -90,11 +90,11 @@
struct CcnxContentStoreOrderedPrefix
{
typedef
- CcnxContentStoreContainer::type::index<ordered>::type
+ CcnxContentStoreContainer::type::index<i_ordered>::type
type;
};
#else
-#define DUMP_INDEX_TAG mru
+#define DUMP_INDEX_TAG i_mru
#define DUMP_INDEX CcnxContentStoreByMru
#endif
@@ -151,12 +151,12 @@
Ptr<Packet>
CcnxContentStore::Lookup (Ptr<const CcnxInterestHeader> interest)
{
- CcnxContentStoreContainer::type::iterator it = m_contentStore.get<hash> ().find (interest->GetName ());
+ CcnxContentStoreContainer::type::iterator it = m_contentStore.get<i_prefix> ().find (interest->GetName ());
if (it != m_contentStore.end ())
{
// promote entry to the top
- m_contentStore.get<mru> ().relocate (m_contentStore.get<mru> ().begin (),
- m_contentStore.project<mru> (it));
+ m_contentStore.get<i_mru> ().relocate (m_contentStore.get<i_mru> ().begin (),
+ m_contentStore.project<i_mru> (it));
// return fully formed CCNx packet
return it->GetFullyFormedCcnxPacket ();
@@ -167,18 +167,18 @@
void
CcnxContentStore::Add (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet)
{
- CcnxContentStoreContainer::type::iterator it = m_contentStore.get<hash> ().find (header->GetName ());
+ CcnxContentStoreContainer::type::iterator it = m_contentStore.get<i_prefix> ().find (header->GetName ());
if (it == m_contentStore.end ())
{ // add entry to the top
- m_contentStore.get<mru> ().push_front (CcnxContentStoreEntry (header, packet));
+ m_contentStore.get<i_mru> ().push_front (CcnxContentStoreEntry (header, packet));
if (m_contentStore.size () > m_maxSize)
- m_contentStore.get<mru> ().pop_back ();
+ m_contentStore.get<i_mru> ().pop_back ();
}
else
{
// promote entry to the top
- m_contentStore.get<mru> ().relocate (m_contentStore.get<mru> ().begin (),
- m_contentStore.project<mru> (it));
+ m_contentStore.get<i_mru> ().relocate (m_contentStore.get<i_mru> ().begin (),
+ m_contentStore.project<i_mru> (it));
}
}
diff --git a/model/ccnx-content-store.h b/model/ccnx-content-store.h
index b9a8138..c82fb8a 100644
--- a/model/ccnx-content-store.h
+++ b/model/ccnx-content-store.h
@@ -36,6 +36,7 @@
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
+#include "ccnx.h"
#include "hash-helper.h"
#include "ccnx-content-object-header.h"
#include "ccnx-interest-header.h"
@@ -111,19 +112,6 @@
/**
* \ingroup ccnx
- * \brief Private namespace for CCNx content store implementation
- */
-namespace __ccnx_private_content_store
-{
-class hash {}; ///< tag for Boost.Multiindex container (hashed prefix)
-class mru {}; ///< tag for Boost.Multiindex container (most recent used index)
-#ifdef _DEBUG
-class ordered {}; ///< tag for Boost.MultiIndex container (ordered by prefix)
-#endif
-};
-
-/**
- * \ingroup ccnx
* \brief Typedef for content store container implemented as a Boost.MultiIndex container
*
* - First index (tag<prefix>) is a unique hash index based on NDN prefix of the stored content.
@@ -139,16 +127,16 @@
CcnxContentStoreEntry,
boost::multi_index::indexed_by<
boost::multi_index::hashed_unique<
- boost::multi_index::tag<__ccnx_private_content_store::hash>,
+ boost::multi_index::tag<__ccnx_private::i_prefix>,
boost::multi_index::const_mem_fun<CcnxContentStoreEntry,
const CcnxNameComponents&,
&CcnxContentStoreEntry::GetName>,
CcnxPrefixHash>,
- boost::multi_index::sequenced<boost::multi_index::tag<__ccnx_private_content_store::mru> >
+ boost::multi_index::sequenced<boost::multi_index::tag<__ccnx_private::i_mru> >
#ifdef _DEBUG
,
boost::multi_index::ordered_unique<
- boost::multi_index::tag<__ccnx_private_content_store::ordered>,
+ boost::multi_index::tag<__ccnx_private::i_ordered>,
boost::multi_index::const_mem_fun<CcnxContentStoreEntry,
const CcnxNameComponents&,
&CcnxContentStoreEntry::GetName>
@@ -162,20 +150,10 @@
* \ingroup ccnx
* \brief NDN content store entry
*/
-class CcnxContentStore : public Object
+class CcnxContentStore
{
public:
/**
- * \brief Interface ID
- *
- * \return interface ID
- */
- static TypeId GetTypeId ();
-
- // typedef string_key_hash_t<CsEntry>::iterator CsIterator;
- // typedef string_key_hash_t<CsEntry>::iterator CsRangeIterator;
-
- /**
* Default constructor
*/
CcnxContentStore( );
diff --git a/model/ccnx-face.h b/model/ccnx-face.h
index a1ef3e0..2650515 100644
--- a/model/ccnx-face.h
+++ b/model/ccnx-face.h
@@ -190,6 +190,12 @@
std::ostream& operator<< (std::ostream& os, const CcnxFace &face);
+inline bool
+operator < (const Ptr<CcnxFace> &lhs, const Ptr<CcnxFace> &rhs)
+{
+ return *lhs < *rhs;
+}
+
void
CcnxFace::SetId (uint32_t id)
{
diff --git a/model/ccnx-fib.cc b/model/ccnx-fib.cc
index d5b1043..b7ed57f 100644
--- a/model/ccnx-fib.cc
+++ b/model/ccnx-fib.cc
@@ -25,6 +25,11 @@
#include "ccnx-interest-header.h"
#include "ns3/node.h"
+#include "ns3/assert.h"
+
+#define NDN_RTO_ALPHA 0.125
+#define NDN_RTO_BETA 0.25
+#define NDN_RTO_K 4
//#define NDN_DEBUG_OSPF 0
//#define NDN_DEBUG_OSPF_NODES 0
@@ -36,7 +41,7 @@
//////////////////////////////////////////////////////////////////////
// Helpers
//////////////////////////////////////////////////////////////////////
-namespace __ccnx_private_fib {
+namespace __ccnx_private {
struct CcnxFibFaceMetricByFace
{
@@ -46,46 +51,67 @@
struct ChangeStatus
{
- ChangeStatus (uint8_t status) : m_status (status) { }
+ ChangeStatus (CcnxFibFaceMetric::Status status) : m_status (status) { }
void operator() (CcnxFibFaceMetric &entry)
{
entry.m_status = m_status;
}
private:
- uint8_t m_status;
+ CcnxFibFaceMetric::Status m_status;
};
-struct SearchByFace {
- /**
- * \brief To perform effective searches by CcnxFace
- */
- bool
- operator() (const CcnxFibFaceMetric &m, const Ptr<CcnxFace> &face) const
- {
- return *(m.m_face) < *face;
- }
+// struct SearchByFace {
+// /**
+// * \brief To perform effective searches by CcnxFace
+// */
+// bool
+// operator() (const CcnxFibFaceMetric &m, const Ptr<CcnxFace> &face) const
+// {
+// return *(m.m_face) < *face;
+// }
- /**
- * \brief To perform effective searches by CcnxFace
- */
- bool
- operator() (const Ptr<CcnxFace> &face, const CcnxFibFaceMetric &m) const
- {
- return *face < *(m.m_face);
- }
-};
+// /**
+// * \brief To perform effective searches by CcnxFace
+// */
+// bool
+// operator() (const Ptr<CcnxFace> &face, const CcnxFibFaceMetric &m) const
+// {
+// return *face < *(m.m_face);
+// }
+// };
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
-using namespace __ccnx_private_fib;
+using namespace __ccnx_private;
void
-CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, uint8_t status)
+CcnxFibFaceMetric::UpdateRtt::operator() (CcnxFibFaceMetric &entry)
{
- CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face, SearchByFace());
+ // const Time & this->m_rttSample
+
+ //update srtt and rttvar (RFC 2988)
+ if (entry.m_sRtt.IsZero ())
+ {
+ //first RTT measurement
+ NS_ASSERT_MSG (entry.m_rttVar.IsZero (), "SRTT is zero, but variation is not");
+
+ entry.m_sRtt = m_rttSample;
+ entry.m_rttVar = Time (entry.m_sRtt / 2.0);
+ }
+ else
+ {
+ entry.m_rttVar = Time ((1 - NDN_RTO_BETA) * entry.m_rttVar + NDN_RTO_BETA * Abs(entry.m_sRtt - m_rttSample));
+ entry.m_sRtt = Time ((1 - NDN_RTO_ALPHA) * entry.m_sRtt + NDN_RTO_ALPHA * m_rttSample);
+ }
+}
+
+void
+CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
+{
+ CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
NS_ASSERT_MSG (record != m_faces.get<i_face> ().end (), "Update status can be performed only on existing faces of CcxnFibEntry");
m_faces.modify (record, ChangeStatus (status));
@@ -157,7 +183,6 @@
std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric)
{
static const std::string statusString[] = {"","g","y","r"};
- NS_ASSERT_MSG (1<=metric.m_status && metric.m_status<=3, "Status can be only GREEN, YELLOW, or RED");
os << metric.m_face << "(" << metric.m_routingCost << ","<< statusString [metric.m_status] << ")";
return os;
diff --git a/model/ccnx-fib.h b/model/ccnx-fib.h
index cb0c8f7..5b16e81 100644
--- a/model/ccnx-fib.h
+++ b/model/ccnx-fib.h
@@ -23,6 +23,7 @@
#include "hash-helper.h"
#include "ccnx-face.h"
+#include "ccnx.h"
#include "ns3/nstime.h"
#include "ns3/simple-ref-count.h"
@@ -39,19 +40,6 @@
namespace ns3 {
-namespace __ccnx_private_fib
-{
-const uint8_t NDN_FIB_GREEN = 1; ///< \brief
-const uint8_t NDN_FIB_YELLOW = 2;
-const uint8_t NDN_FIB_RED = 3;
-
-class i_face {};
-class i_metric {};
-class i_nth {};
-class i_prefix {};
-}
-
-class Ccnx;
class CcnxInterestHeader;
/**
@@ -61,6 +49,10 @@
class CcnxFibFaceMetric
{
public:
+ enum Status { NDN_FIB_GREEN = 1,
+ NDN_FIB_YELLOW = 2,
+ NDN_FIB_RED = 3 };
+public:
/**
* \brief Metric constructor
*
@@ -69,7 +61,7 @@
*/
CcnxFibFaceMetric (Ptr<CcnxFace> face, int cost)
: m_face (face)
- , m_status (__ccnx_private_fib::NDN_FIB_YELLOW)
+ , m_status (NDN_FIB_YELLOW)
, m_routingCost (cost)
, m_sRtt (Seconds (0))
, m_rttVar (Seconds (0))
@@ -79,20 +71,35 @@
* \brief Comparison operator used by boost::multi_index::identity<>
*/
bool
- operator< (const CcnxFibFaceMetric &m) const { return *m_face < *(m.m_face); } // return identity of the face
+ operator< (const CcnxFibFaceMetric &fm) const { return *m_face < *fm.m_face; } // return identity of the face
+
+ bool
+ operator< (const Ptr<CcnxFace> &face) const { return *m_face < *face; }
Ptr<CcnxFace>
GetFace () const { return m_face; }
+
+ /**
+ * \brief Unary function to recalculate smoothed RTT and RTT variation
+ * \param rttSample RTT sample
+ */
+ struct UpdateRtt
+ {
+ UpdateRtt (const Time &rttSample) : m_rttSample (rttSample) {};
+ void operator() (CcnxFibFaceMetric &entry);
+ private:
+ const Time &m_rttSample;
+ };
private:
friend std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric);
public:
Ptr<CcnxFace> m_face; ///< Face
- uint8_t m_status; ///< \brief Status of the next hop:
- ///< - #__ccnx_private_fib::NDN_FIB_GREEN
- ///< - #__ccnx_private_fib::NDN_FIB_YELLOW
- ///< - #__ccnx_private_fib::NDN_FIB_RED
+ Status m_status; ///< \brief Status of the next hop:
+ ///< - NDN_FIB_GREEN
+ ///< - NDN_FIB_YELLOW
+ ///< - NDN_FIB_RED
uint32_t m_routingCost; ///< \brief routing protocol cost (interpretation of the value depends on the underlying routing protocol)
@@ -117,23 +124,23 @@
boost::multi_index::indexed_by<
// For fast access to elements using CcnxFace
boost::multi_index::ordered_unique<
- boost::multi_index::tag<__ccnx_private_fib::i_face>,
- boost::multi_index::identity<CcnxFibFaceMetric>
+ boost::multi_index::tag<__ccnx_private::i_face>,
+ boost::multi_index::member<CcnxFibFaceMetric,Ptr<CcnxFace>,&CcnxFibFaceMetric::m_face>
>,
// List of available faces ordered by (status, m_routingCost)
boost::multi_index::ordered_non_unique<
- boost::multi_index::tag<__ccnx_private_fib::i_metric>,
+ boost::multi_index::tag<__ccnx_private::i_metric>,
boost::multi_index::composite_key<
CcnxFibFaceMetric,
- boost::multi_index::member<CcnxFibFaceMetric,uint8_t,&CcnxFibFaceMetric::m_status>,
+ boost::multi_index::member<CcnxFibFaceMetric,CcnxFibFaceMetric::Status,&CcnxFibFaceMetric::m_status>,
boost::multi_index::member<CcnxFibFaceMetric,uint32_t,&CcnxFibFaceMetric::m_routingCost>
>
>,
// To optimize nth candidate selection (sacrifice a little bit space to gain speed)
boost::multi_index::random_access<
- boost::multi_index::tag<__ccnx_private_fib::i_nth>
+ boost::multi_index::tag<__ccnx_private::i_nth>
>
>
> type;
@@ -160,7 +167,7 @@
* \brief Update status of FIB next hop
*/
void
- UpdateStatus (Ptr<CcnxFace> face, uint8_t status);
+ UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status);
/**
* \brief Get prefix for the FIB entry
@@ -177,7 +184,7 @@
private:
friend std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry);
-private:
+public:
Ptr<CcnxNameComponents> m_prefix; ///< \brief Prefix of the FIB entry
CcnxFibFaceMetricContainer::type m_faces; ///< \brief Indexed list of faces
@@ -201,7 +208,7 @@
boost::multi_index::indexed_by<
// For fast access to elements using CcnxFace
boost::multi_index::hashed_unique<
- boost::multi_index::tag<__ccnx_private_fib::i_prefix>,
+ boost::multi_index::tag<__ccnx_private::i_prefix>,
boost::multi_index::const_mem_fun<CcnxFibEntry,
const CcnxNameComponents&,
&CcnxFibEntry::GetPrefix>,
@@ -270,9 +277,6 @@
// // Update Fib from IP routing table
// void updateFibFromIpRouting( );
- // // Update the status for all FIB records for the specified interface
- // void updateInterfaceStatus( int interface, int status );
-
// void dump( );
// void dump( const FibIterator &fib );
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index 2909b38..1ba7488 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -179,7 +179,7 @@
if (face->IsUp ())
{
NS_LOG_LOGIC ("Dropping received packet -- interface is down");
- m_dropTrace (p, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
+ // m_dropTrace (p, INTERFACE_DOWN, m_node->GetObject<Ccnx> ()/*this*/, face);
return;
}
NS_LOG_LOGIC ("Packet from face " << &face << " received on node " << m_node->GetId ());
@@ -193,13 +193,25 @@
case CcnxHeaderHelper::INTEREST:
{
Ptr<CcnxInterestHeader> header = Create<CcnxInterestHeader> ();
- OnInterest (face, header, packet);
+
+ // Deserialization. Exception may be thrown
+ packet->RemoveHeader (*header);
+ NS_ASSERT_MSG (packet->GetSize () == 0, "Payload of Interests should be zero");
+
+ OnInterest (face, header, p/*original packet*/);
break;
}
case CcnxHeaderHelper::CONTENT_OBJECT:
{
Ptr<CcnxContentObjectHeader> header = Create<CcnxContentObjectHeader> ();
- OnData (face, header, packet);
+
+ static CcnxContentObjectTail contentObjectTrailer; //there is no data in this object
+
+ // Deserialization. Exception may be thrown
+ packet->RemoveHeader (*header);
+ packet->RemoveTrailer (contentObjectTrailer);
+
+ OnData (face, header, packet/*payload*/, p/*original packet*/);
break;
}
}
@@ -215,15 +227,11 @@
// Processing Interests
void CcnxL3Protocol::OnInterest (const Ptr<CcnxFace> &incomingFace,
Ptr<CcnxInterestHeader> &header,
- Ptr<Packet> &packet)
+ const Ptr<const Packet> &packet)
{
NS_LOG_LOGIC ("Receiving interest from " << &incomingFace);
- m_receivedInterestsTrace (packet, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
+ m_receivedInterestsTrace (header, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
- // dangerous place. Trying to deserialize header
- packet->RemoveHeader (*header);
-
- NS_ASSERT_MSG (packet->GetSize () == 0, "Payload of Interests should be zero");
/// \todo Processing of Interest packets
@@ -241,20 +249,71 @@
// Processing ContentObjects
void CcnxL3Protocol::OnData (const Ptr<CcnxFace> &incomingFace,
Ptr<CcnxContentObjectHeader> &header,
- Ptr<Packet> &packet)
+ Ptr<Packet> &payload,
+ const Ptr<const Packet> &packet)
{
- static CcnxContentObjectTail contentObjectTrailer; //there is no data in this object
NS_LOG_LOGIC ("Receiving contentObject from " << &incomingFace);
- m_receivedDataTrace (packet, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
+ m_receivedDataTrace (header, payload, m_node->GetObject<Ccnx> ()/*this*/, incomingFace);
- // dangerous place. Trying to deserialize header
- packet->RemoveHeader (*header);
- packet->RemoveTrailer (contentObjectTrailer);
+ // 1. Lookup PIT entry
+ try
+ {
+ const CcnxPitEntry &pitEntry = m_pit.Lookup (*header);
+
+ // Note that with MultiIndex we need to modify entries indirectly
- /// \todo Processing of ContentObject packets
-}
+ // Update metric status for the incoming interface in the corresponding FIB entry
+ m_pit.modify (m_pit.iterator_to (pitEntry),
+ CcnxPitEntry::UpdateFibStatus (incomingFace, CcnxFibFaceMetric::NDN_FIB_GREEN));
+
+ // Add or update entry in the content store
+ m_contentStore.Add (header, payload);
+ CcnxPitEntryOutgoingFaceContainer::type::iterator
+ out = pitEntry.m_outgoing.find (incomingFace);
+
+ // If we have sent interest for this data via this face, then update stats.
+ if (out != pitEntry.m_outgoing.end ())
+ {
+ m_pit.modify (m_pit.iterator_to (pitEntry), CcnxPitEntry::EstimateRttAndRemoveFace(out));
+ // face will be removed in the above call
+ }
+ else
+ {
+ NS_LOG_WARN ("Node "<< m_node->GetId() <<
+ ". PIT entry for "<< header->GetName ()<<" is valid, "
+ "but outgoing entry for interface "<< incomingFace <<" doesn't exist\n");
+ }
+
+ //satisfy all pending incoming Interests
+ BOOST_FOREACH (const CcnxPitEntryIncomingFace &interest, pitEntry.m_incoming)
+ {
+ if (interest.m_face == incomingFace) continue;
+
+ // may not work either because of 'const' thing
+ interest.m_face->Send (packet->Copy ()); // unfortunately, we have to copy packet...
+ m_transmittedDataTrace (header, payload, FORWARDED, m_node->GetObject<Ccnx> (), interest.m_face);
+ }
+
+ m_pit.modify (m_pit.iterator_to (pitEntry), CcnxPitEntry::ClearIncoming()); // satisfy all incoming interests
+
+ if( pitEntry.m_outgoing.size()==0 ) // remove PIT when all outgoing interests are "satisfied"
+ {
+ m_pit.erase (m_pit.iterator_to (pitEntry));
+ }
+
+ }
+ catch (CcnxPitEntryNotFound)
+ {
+ // 2. Drop data packet if PIT entry is not found
+ // (unsolicited data packets should not "poison" content store)
+
+ //drop dulicated or not requested data packet
+ m_droppeddDataTrace (header, payload, NDN_UNSOLICITED_DATA, m_node->GetObject<Ccnx> (), incomingFace);
+ return; // do not process unsoliced data packets
+ }
+}
void
CcnxL3Protocol::Send (const Ptr<CcnxFace> &face, const Ptr<Packet> &packet)
@@ -272,7 +331,7 @@
else
{
NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
- m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
+ // m_dropTrace (packet, INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
}
}
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index fd03be9..2cd81ea 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -89,11 +89,23 @@
*/
enum DropReason
{
- /** \todo Fill reasons from QualNet code */
- DROP_DUPLICATE_INTEREST=1, /**< Duplicate Interest */
+ NDN_DUPLICATE_INTEREST, ///< \brief Duplicate Interest
+ NDN_UNSOLICITED_DATA, ///< \brief Unsolicited ContentObject (duplicate?)
+ // INTERFACE_DOWN, ///< \brief Interface is down
+
DROP_CONGESTION, /**< Congestion detected */
DROP_NO_ROUTE, /**< No route to host */
- DROP_INTERFACE_DOWN, /**< Interface is down so can not send packet */
+ };
+
+ /**
+ * \enum DropReason
+ * \brief Description of where content object was originated
+ */
+ enum ContentObjectSource
+ {
+ APPLICATION,
+ FORWARDED,
+ CACHED
};
/**
@@ -118,25 +130,33 @@
protected:
/**
- * \brief Actual processing of incoming CCNx interests
+ * \brief Actual processing of incoming CCNx interests. Note, interests do not have payload
*
* Processing Interest packets
+ * @param face incoming face
+ * @param header deserialized Interest header
+ * @param packet original packet
*/
virtual void
OnInterest (const Ptr<CcnxFace> &face,
Ptr<CcnxInterestHeader> &header,
- Ptr<Packet> &p);
+ const Ptr<const Packet> &p);
/**
* \brief Actual processing of incoming CCNx content objects
*
* Processing ContentObject packets
+ * @param face incoming face
+ * @param header deserialized ContentObject header
+ * @param payload data packet payload
+ * @param packet original packet
*/
virtual void
OnData (const Ptr<CcnxFace> &face,
Ptr<CcnxContentObjectHeader> &header,
- Ptr<Packet> &p);
+ Ptr<Packet> &payload,
+ const Ptr<const Packet> &packet);
protected:
virtual void DoDispose (void);
@@ -171,17 +191,31 @@
CcnxContentStore m_contentStore; ///< \brief Content store (for caching purposes only)
- TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedInterestsTrace;
- TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedInterestsTrace;
+ TracedCallback<Ptr<const CcnxInterestHeader>,
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedInterestsTrace;
+ TracedCallback<Ptr<const CcnxInterestHeader>,
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedInterestsTrace;
+ TracedCallback<Ptr<const CcnxInterestHeader>,
+ DropReason,
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_droppedInterestsTrace;
- TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedDataTrace;
- TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedDataTrace;
+ TracedCallback<Ptr<const CcnxContentObjectHeader>,
+ Ptr<const Packet>,/*payload*/
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_receivedDataTrace;
+ TracedCallback<Ptr<const CcnxContentObjectHeader>,
+ Ptr<const Packet>,/*payload*/
+ ContentObjectSource,
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_transmittedDataTrace;
+ TracedCallback<Ptr<const CcnxContentObjectHeader>,
+ Ptr<const Packet>,/*payload*/
+ DropReason,
+ Ptr<Ccnx>, Ptr<const CcnxFace> > m_droppeddDataTrace;
/**
* \brief Trace of dropped packets, including reason and all headers
* \internal
*/
- TracedCallback<Ptr<const Packet>, DropReason, Ptr<const Ccnx>, Ptr<const CcnxFace> > m_dropTrace;
+ // TracedCallback<Ptr<const Packet>, DropReason, Ptr<const Ccnx>, Ptr<const CcnxFace> > m_dropTrace;
};
} // Namespace ns3
diff --git a/model/ccnx-pit-entry-outgoing-face.cc b/model/ccnx-pit-entry-outgoing-face.cc
index c15df71..ccdfb08 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 d5fc4da..502f333 100644
--- a/model/ccnx-pit-entry-outgoing-face.h
+++ b/model/ccnx-pit-entry-outgoing-face.h
@@ -38,7 +38,7 @@
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)
- // int 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
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index a6629d0..b9ca8d4 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -22,6 +22,8 @@
#include "ccnx-name-components.h"
#include "ccnx-fib.h"
+#include "ns3/simulator.h"
+
namespace ns3
{
@@ -98,15 +100,21 @@
}
void
+CcnxPitEntry::DeleteIncoming::operator() (CcnxPitEntry &entry)
+{
+ entry.m_incoming.erase (m_face);
+}
+
+void
CcnxPitEntry::AddOutgoing::operator() (CcnxPitEntry &entry)
{
entry.m_outgoing.insert (CcnxPitEntryOutgoingFace (m_face));
}
void
-CcnxPitEntry::DeleteIncoming::operator() (CcnxPitEntry &entry)
+CcnxPitEntry::DeleteOutgoing::operator() (CcnxPitEntry &entry)
{
- entry.m_incoming.erase (m_face);
+ entry.m_outgoing.erase (m_face);
}
void
@@ -115,5 +123,33 @@
entry.m_incoming.clear ();
}
+CcnxPitEntry::UpdateFibStatus::UpdateFibStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
+ : m_face (face)
+ , m_status (status)
+{
+}
+
+void
+CcnxPitEntry::UpdateFibStatus::operator() (CcnxPitEntry &entry)
+{
+ entry.m_fib->UpdateStatus (m_face, m_status);
+}
+
+void
+CcnxPitEntry::EstimateRttAndRemoveFace::operator() (CcnxPitEntry &entry)
+{
+ // similar to Karn's Algorithm, we don't use RTT measurements for retx packets
+ if (m_outFace->m_retxNum>0)
+ return;
+
+ CcnxFibFaceMetricContainer::type::iterator metric = entry.m_fib->m_faces.find (m_outFace->m_face);
+ NS_ASSERT_MSG (metric != entry.m_fib->m_faces.end (),
+ "Something wrong. Cannot find entry for the face in FIB");
+
+ Time rtt = Simulator::Now() - m_outFace->m_sendTime;
+ entry.m_fib->m_faces.modify (metric, CcnxFibFaceMetric::UpdateRtt (rtt));
+
+ entry.m_outgoing.erase (m_outFace);
+}
}
diff --git a/model/ccnx-pit-entry.h b/model/ccnx-pit-entry.h
index 5da3c4c..842bd88 100644
--- a/model/ccnx-pit-entry.h
+++ b/model/ccnx-pit-entry.h
@@ -44,7 +44,7 @@
namespace __ccnx_private
{
-class i_face {};
+// class i_face {};
}
/**
@@ -62,7 +62,7 @@
// For fast access to elements using CcnxFace
boost::multi_index::ordered_unique<
boost::multi_index::tag<__ccnx_private::i_face>,
- boost::multi_index::identity<CcnxPitEntryIncomingFace>
+ boost::multi_index::member<CcnxPitEntryIncomingFace, Ptr<CcnxFace>, &CcnxPitEntryIncomingFace::m_face>
>
>
> type;
@@ -83,7 +83,7 @@
// For fast access to elements using CcnxFace
boost::multi_index::ordered_unique<
boost::multi_index::tag<__ccnx_private::i_face>,
- boost::multi_index::identity<CcnxPitEntryOutgoingFace>
+ boost::multi_index::member<CcnxPitEntryOutgoingFace, Ptr<CcnxFace>, &CcnxPitEntryOutgoingFace::m_face>
>
>
> type;
@@ -137,6 +137,18 @@
};
/**
+ * \brief Unary function to delete incoming interest for the interface
+ * \param face face that should be removed from the list of incoming interests
+ */
+ struct DeleteIncoming
+ {
+ DeleteIncoming (Ptr<CcnxFace> face) : m_face (face) {}
+ void operator() (CcnxPitEntry &entry);
+ private:
+ Ptr<CcnxFace> m_face;
+ };
+
+ /**
* \brief Unary function to add outgoing interest to PIT entry
*
* \param outgoingFace smart pointer to the face of the outgoing interest
@@ -155,9 +167,9 @@
* \brief Unary function to delete incoming interest for the interface
* \param face face that should be removed from the list of incoming interests
*/
- struct DeleteIncoming
+ struct DeleteOutgoing
{
- DeleteIncoming (Ptr<CcnxFace> face) : m_face (face) {}
+ DeleteOutgoing (Ptr<CcnxFace> face) : m_face (face) {}
void operator() (CcnxPitEntry &entry);
private:
Ptr<CcnxFace> m_face;
@@ -168,10 +180,35 @@
*/
struct ClearIncoming
{
- ClearIncoming ();
+ ClearIncoming () {};
void operator() (CcnxPitEntry &entry);
};
+ /**
+ * \brief Unary function to update FIB status
+ */
+ struct UpdateFibStatus
+ {
+ UpdateFibStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status);
+ void operator() (CcnxPitEntry &entry);
+ private:
+ Ptr<CcnxFace> m_face;
+ CcnxFibFaceMetric::Status m_status;
+ };
+
+ /**
+ * \brief Unary function to estimate RTT and update smoothed RTT value in FIB
+ * \param outFace iterator of the outgoing face entry
+ */
+ struct EstimateRttAndRemoveFace
+ {
+ EstimateRttAndRemoveFace (CcnxPitEntryOutgoingFaceContainer::type::iterator outFace)
+ : m_outFace (outFace) { };
+ void operator() (CcnxPitEntry &entry);
+ private:
+ CcnxPitEntryOutgoingFaceContainer::type::iterator m_outFace;
+ };
+
const CcnxNameComponents &
GetPrefix () const;
@@ -181,7 +218,7 @@
private:
friend std::ostream& operator<< (std::ostream& os, const CcnxPitEntry &entry);
-private:
+public:
Ptr<CcnxNameComponents> m_prefix; ///< \brief Prefix of the PIT entry
Ptr<CcnxFibEntry> m_fib; ///< \brief FIB entry related to this prefix
diff --git a/model/ccnx-pit.cc b/model/ccnx-pit.cc
index 7ee9d83..15e4824 100644
--- a/model/ccnx-pit.cc
+++ b/model/ccnx-pit.cc
@@ -28,7 +28,7 @@
namespace ns3 {
-NS_OBJECT_ENSURE_REGISTERED (CcnxPit);
+// NS_OBJECT_ENSURE_REGISTERED (CcnxPit);
using namespace __ccnx_private;
@@ -50,22 +50,22 @@
// return count;
// }
-TypeId
-CcnxPit::GetTypeId ()
-{
- static TypeId tid = TypeId ("ns3::CcnxPit")
- .SetGroupName ("Ccnx")
- .SetParent<Object> ()
- .AddConstructor<CcnxPit> ()
- .AddAttribute ("CleanupTimeout",
- "Timeout defining how frequent RIT should be cleaned up",
- TimeValue (Seconds (1)),
- MakeTimeAccessor (&CcnxPit::GetCleanupTimeout, &CcnxPit::SetCleanupTimeout),
- MakeTimeChecker ())
- ;
+// TypeId
+// CcnxPit::GetTypeId ()
+// {
+// static TypeId tid = TypeId ("ns3::CcnxPit")
+// .SetGroupName ("Ccnx")
+// .SetParent<Object> ()
+// .AddConstructor<CcnxPit> ()
+// .AddAttribute ("CleanupTimeout",
+// "Timeout defining how frequent RIT should be cleaned up",
+// TimeValue (Seconds (1)),
+// MakeTimeAccessor (&CcnxPit::GetCleanupTimeout, &CcnxPit::SetCleanupTimeout),
+// MakeTimeChecker ())
+// ;
- return tid;
-}
+// return tid;
+// }
CcnxPit::CcnxPit ()
{
@@ -94,11 +94,11 @@
NS_LOG_LOGIC ("Cleaning PIT");
Time now = Simulator::Now ();
- while( !m_pit.empty() )
+ while( !empty() )
{
- if( m_pit.get<i_timestamp> ().front ().GetExpireTime () <= now ) // is the record stale?
+ if( get<i_timestamp> ().front ().GetExpireTime () <= now ) // is the record stale?
{
- m_pit.get<i_timestamp> ().pop_front( );
+ get<i_timestamp> ().pop_front( );
}
else
break; // nothing else to do. All later records will not be stale
@@ -113,9 +113,9 @@
CcnxPit::Lookup (const CcnxContentObjectHeader &header) const
{
CcnxPitEntryContainer::type::iterator entry =
- m_pit.get<i_prefix> ().find (header.GetName ());
+ get<i_prefix> ().find (header.GetName ());
- if (entry != m_pit.end ())
+ if (entry != end ())
throw CcnxPitEntryNotFound();
return *entry;
@@ -125,7 +125,7 @@
CcnxPit::Lookup (const CcnxInterestHeader &header) const
{
CcnxPitEntryContainer::type::iterator entry =
- m_pit.get<i_prefix> ().find (header.GetName ());
+ get<i_prefix> ().find (header.GetName ());
// if (entry != m_pit.end ())
// entry = m_pit.insert (m_pit.end (), CcnxPitEntry (Create<CcnxNameComponents> (header.GetName ())));
diff --git a/model/ccnx-pit.h b/model/ccnx-pit.h
index 3ffadad..02a2ac7 100644
--- a/model/ccnx-pit.h
+++ b/model/ccnx-pit.h
@@ -52,7 +52,7 @@
*/
namespace __ccnx_private
{
-class i_prefix{}; ///< tag for prefix hash
+// class i_prefix{}; ///< tag for prefix hash
class i_timestamp {}; ///< tag for timestamp-ordered records (for cleanup optimization)
};
@@ -100,17 +100,10 @@
* \ingroup ccnx
* \brief Class implementing Pending Interests Table
*/
-class CcnxPit : public Object
+class CcnxPit : public CcnxPitEntryContainer::type
{
public:
/**
- * \brief Interface ID
- *
- * \return interface ID
- */
- static TypeId GetTypeId ();
-
- /**
* \brief PIT constructor
*/
CcnxPit ();
@@ -175,8 +168,6 @@
friend std::ostream& operator<< (std::ostream& os, const CcnxPit &fib);
private:
- CcnxPitEntryContainer::type m_pit; ///< \brief Container for PIT entries
-
Time m_cleanupTimeout; ///< \brief Configurable timeout of how often cleanup events are working
EventId m_cleanupEvent; ///< \brief Cleanup event
diff --git a/model/ccnx.h b/model/ccnx.h
index 7c0e1d0..6d8461e 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -25,15 +25,27 @@
#include "ns3/socket.h"
#include "ns3/callback.h"
-#include "ccnx-face.h"
-#include "ccnx-content-store.h"
-
namespace ns3 {
class Node;
class NetDevice;
class Packet;
class CcnxForwardingStrategy;
+class CcnxFace;
+
+/**
+ * \internal
+ * \brief Private namespace for CCNx content store implementation
+ */
+namespace __ccnx_private
+{
+class i_face {};
+class i_metric {};
+class i_nth {};
+class i_prefix {};
+class i_ordered {}; ///< tag for Boost.MultiIndex container (ordered by prefix)
+class i_mru {};
+}
/**
* \defgroup ccnx NDN abstraction
@@ -141,8 +153,6 @@
*/
virtual Ptr<CcnxFace>
GetFace (uint32_t face) const = 0;
-
- Ptr<CcnxContentStore> m_contentStore;
};
} // namespace ns3