Implementing content store using Boost.MultiIndex container
Adding .SetGroupName("Ccnx") call to Ccnx-related objects (probably
missed some). This call is advisory, but it is nice to give users
information about Ccnx-related objects (this information is accessible
via --PrintGroup=Ccnx command line argument)
diff --git a/model/ccnx-content-object-header.cc b/model/ccnx-content-object-header.cc
index e567207..d1ad0cf 100644
--- a/model/ccnx-content-object-header.cc
+++ b/model/ccnx-content-object-header.cc
@@ -37,6 +37,7 @@
CcnxContentObjectHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CcnxContentObjectHeader")
+ .SetGroupName ("Ccnx")
.SetParent<Header> ()
.AddConstructor<CcnxContentObjectHeader> ()
;
diff --git a/model/ccnx-content-object-header.h b/model/ccnx-content-object-header.h
index c26052b..97a8d3d 100644
--- a/model/ccnx-content-object-header.h
+++ b/model/ccnx-content-object-header.h
@@ -24,6 +24,7 @@
#include "ns3/integer.h"
#include "ns3/header.h"
+#include "ns3/trailer.h"
#include <string>
#include <vector>
@@ -101,7 +102,7 @@
* ContentObjectTail should always be 2 bytes, representing two closing tags:
* "</Content><ContentObject>"
*/
-class CcnxContentObjectTail : public Header
+class CcnxContentObjectTail : public Trailer
{
public:
CcnxContentObjectTail ();
diff --git a/model/ccnx-content-store.cc b/model/ccnx-content-store.cc
index 31a9fb3..4633000 100644
--- a/model/ccnx-content-store.cc
+++ b/model/ccnx-content-store.cc
@@ -16,88 +16,135 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
+ * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
*/
#include "ccnx-content-store.h"
#include "ns3/log.h"
-
+#include "ns3/packet.h"
+#include "ns3/ccnx-interest-header.h"
+#include "ns3/ccnx-content-object-header.h"
+#include "ns3/uinteger.h"
NS_LOG_COMPONENT_DEFINE ("CcnxContentStore");
namespace ns3
{
-
-CcnxContentStore::CcnxContentStore( int maxSize )
- : m_maxSize(maxSize) { }
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxContentStore);
+
+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> ())
+ ;
+
+ return tid;
+}
+
+CcnxContentObjectTail CcnxContentStoreEntry::m_tail;
+
+CcnxContentStoreEntry::CcnxContentStoreEntry (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet)
+ : m_header (header)
+{
+ m_packet = packet->Copy ();
+ m_packet->RemoveHeader (*header);
+ m_packet->RemoveTrailer (m_tail);
+}
+
+Ptr<Packet>
+CcnxContentStoreEntry::GetFullyFormedCcnxPacket () const
+{
+ Ptr<Packet> packet = m_packet->Copy ();
+ packet->AddHeader (*m_header);
+ packet->AddTrailer (m_tail);
+ return packet;
+}
+
+// /// Disabled copy constructor
+// CcnxContentStoreEntry::CcnxContentStoreEntry (const CcnxContentStoreEntry &o)
+// {
+// }
+
+// /// Disables copy operator
+// CcnxContentStoreEntry& CcnxContentStoreEntry::operator= (const CcnxContentStoreEntry &o)
+// {
+// return *this;
+// }
+
+
+
+CcnxContentStore::CcnxContentStore( )
+ : m_maxSize(100) { } // this value shouldn't matter, NS-3 should call SetSize with default value specified in AddAttribute earlier
CcnxContentStore::~CcnxContentStore( )
- { }
+{ }
-//Find corresponding CS entry for the given content name
-CsEntry*
-CcnxContentStore::Lookup(const string prefix )
+/// Disabled copy constructor
+CcnxContentStore::CcnxContentStore (const CcnxContentStore &o)
{
- CriticalSection section(m_csMutex);
-
- CsEntry *result = &(m_contentStore.at(prefix));
-
- if(result != NULL)
- Promote (*result);
-
- return result;
+}
+
+/// Disables copy operator
+CcnxContentStore& CcnxContentStore::operator= (const CcnxContentStore &o)
+{
+ return *this;
+}
+
+
+Ptr<Packet>
+CcnxContentStore::Lookup (Ptr<const CcnxInterestHeader> interest)
+{
+ CcnxContentStoreContainer::type::iterator it = m_contentStore.get<hash> ().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));
+
+ // return fully formed CCNx packet
+ return it->GetFullyFormedCcnxPacket ();
+ }
+ return 0;
}
-//move the given CS entry to the head of the list
void
-CcnxContentStore::Promote(CsEntry &ce )
+CcnxContentStore::Add (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet)
{
- // should not lock mutex. Otherwise deadlocks will be welcome
- if( m_LRU.front() == &ce ) return;
-
- //assert( *(ce.lruPosition)==&ce ); // should point to the same object
-
- // swaping positions in _lru
- m_LRU.erase( ce.lruPosition );
- m_LRU.push_front( &ce );
- ce.lruPosition = m_LRU.begin( );
-
- //assert( *(ce.lruPosition)==&ce ); // should point to the same object
-}
-
-//Add entry to content store, if content store is full, use LRU replacement
-void
-CcnxContentStore::Add( const string contentName, int contentSize )
-{
- CriticalSection section(m_csMutex);
-
- m_contentStore.erase(m_contentStore.find(contentName));
-
- if((int)m_contentStore.size() == m_maxSize )
- {
- CsEntry *entry = m_LRU.back();
- m_contentStore.erase(m_contentStore.find(entry->contentName));
- m_LRU.pop_back( );
+ CcnxContentStoreContainer::type::iterator it = m_contentStore.get<hash> ().find (header->GetName ());
+ if (it == m_contentStore.end ())
+ { // add entry to the top
+ m_contentStore.get<mru> ().push_front (CcnxContentStoreEntry (header, packet));
}
-
- CsEntry ce;
- ce.contentName = contentName;
- ce.contentSize = contentSize;
-
- m_contentStore[contentName] = ce;
-
- CsEntry *ce_in_hash = &(m_contentStore.at(contentName));
- m_LRU.push_front( ce_in_hash );
- ce_in_hash->lruPosition = m_LRU.begin( );
-}
-
-void
-CcnxContentStore::Dump()
-{
- CriticalSection section(m_csMutex);
-
- BOOST_FOREACH(string_key_hash_t<CsEntry>::value_type i, m_contentStore)
+ else
{
- NS_LOG_INFO ("Key = " << i.first << " Value = " << i.second.contentName);
+ // promote entry to the top
+ m_contentStore.get<mru> ().relocate (m_contentStore.get<mru> ().begin (),
+ m_contentStore.project<mru> (it));
}
}
-}
\ No newline at end of file
+
+void
+CcnxContentStore::Print() const
+{
+ for( DUMP_INDEX::type::iterator it=m_contentStore.get<DUMP_INDEX_TAG> ().begin ();
+ it != m_contentStore.get<DUMP_INDEX_TAG> ().end ();
+ it++
+ )
+ {
+ NS_LOG_INFO (it->GetName ());
+ }
+}
+
+} // namespace ns3
diff --git a/model/ccnx-content-store.h b/model/ccnx-content-store.h
index 58e060e..ee29f81 100644
--- a/model/ccnx-content-store.h
+++ b/model/ccnx-content-store.h
@@ -18,60 +18,327 @@
* Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
*/
-#ifndef ccnx_content_store_h
-#define ccnx_content_store_h
+#ifndef CCNX_CONTENT_STORE_H
+#define CCNX_CONTENT_STORE_H
-#include <ns3/system-mutex.h>
+#include "ns3/object.h"
+#include "ns3/ptr.h"
+
#include <list>
#include <string>
-#include "hash-helper.h"
+#include <iostream>
-using namespace std;
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/tag.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/sequenced_index.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+
+#include "hash-helper.h"
+#include "ccnx-content-object-header.h"
+#include "ccnx-interest-header.h"
+#include "name-components.h"
namespace ns3
{
-
-class CsEntry;
-typedef list<CsEntry*>::iterator CsLruIterator;
-
-//structure for CS entry
-struct CsEntry
-{
- string contentName;
- int contentSize;
-
- CsLruIterator lruPosition;
-};
-
-typedef string_key_hash_t<CsEntry>::iterator CsIterator;
-typedef string_key_hash_t<CsEntry>::iterator CsRangeIterator;
-
-class CcnxContentStore
+class Packet;
+
+/**
+ * \ingroup ccnx
+ * \brief NDN content store entry
+ *
+ * Content store entry stores separately pseudo header and content of
+ * ContentObject packet. It is responsibility of the caller to
+ * construct a fully formed CcnxPacket by calling Copy(), AddHeader(),
+ * AddTail() on the packet received by GetPacket() method.
+ *
+ * GetFullyFormedCcnxPacket method provided as a convenience
+ */
+class CcnxContentStoreEntry
{
public:
- CcnxContentStore( int max_size=NDN_CONTENT_STORE_SIZE );
- virtual ~CcnxContentStore( );
+ /**
+ * \brief Construct content store entry
+ *
+ * \param header Parsed CcnxContentObject header
+ * \param packet Original CCNx packet
+ *
+ * The constructor will make a copy of the supplied packet and calls
+ * RemoveHeader and RemoveTail on the copy.
+ */
+ CcnxContentStoreEntry (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet);
+
+ /**
+ * \brief Get prefix of the stored entry
+ * \returns prefix of the stored entry
+ */
+ inline const Name::Components&
+ GetName () const;
+
+ /**
+ * \brief Get CcnxContentObjectHeader of the stored entry
+ * \returns CcnxContentObjectHeader of the stored entry
+ */
+ inline Ptr<const CcnxContentObjectHeader>
+ GetHeader () const;
+
+ /**
+ * \brief Get content of the stored entry
+ * \returns content of the stored entry
+ */
+ inline Ptr<const Packet>
+ GetPacket () const;
+
+ /**
+ * \brief Convenience method to create a fully formed CCNx packet from stored header and content
+ * \returns A read-write copy of the packet with CcnxContentObjectHeader and CcxnContentObjectTail
+ */
+ Ptr<Packet>
+ GetFullyFormedCcnxPacket () const;
+
+// Copy constructor is required by the container. Though, we're
+// storing only two pointers, so shouldn't be a problem
+// private:
+// CcnxContentStoreEntry (const CcnxContentStoreEntry &); ///< disabled copy constructor
+// CcnxContentStoreEntry& operator= (const CcnxContentStoreEntry&); ///< disabled copy operator
+
+private:
+ Ptr<CcnxContentObjectHeader> m_header; ///< \brief non-modifiable CcnxContentObjectHeader
+ Ptr<Packet> m_packet; ///< \brief non-modifiable content of the ContentObject packet
+
+ static CcnxContentObjectTail m_tail; ///< \internal for optimization purposes
+};
+
+/// \brief Private namespace for CCNx implementation
+namespace __ccnx_private
+{
+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.
+ * - Second index (tag<mru>) is a sequential index used to maintain up to m_maxSize most recent used (MRU) entries in the content store
+ * - Third index (tag<ordered>) is just a helper to provide stored prefixes in ordered way. Should be disabled in production build
+ *
+ * \see http://www.boost.org/doc/libs/1_46_1/libs/multi_index/doc/ for more information on Boost.MultiIndex library
+ */
+struct CcnxContentStoreContainer
+{
+ typedef
+ boost::multi_index::multi_index_container<
+ CcnxContentStoreEntry,
+ boost::multi_index::indexed_by<
+ boost::multi_index::hashed_unique<
+ boost::multi_index::tag<__ccnx_private::hash>,
+ boost::multi_index::const_mem_fun<CcnxContentStoreEntry,
+ const Name::Components&,
+ &CcnxContentStoreEntry::GetName>,
+ CcnxPrefixHash>,
+ boost::multi_index::sequenced<boost::multi_index::tag<__ccnx_private::mru> >
+#ifdef _DEBUG
+ ,
+ boost::multi_index::ordered_unique<
+ boost::multi_index::tag<__ccnx_private::ordered>,
+ boost::multi_index::const_mem_fun<CcnxContentStoreEntry,
+ const Name::Components&,
+ &CcnxContentStoreEntry::GetName>
+ >
+#endif
+ >
+ > type;
+};
+
+/**
+ * \ingroup ccnx
+ * \brief Typedef for hash index of content store container
+ */
+struct CcnxContentStoreByPrefix
+{
+ typedef
+ CcnxContentStoreContainer::type::index<__ccnx_private::hash>::type
+ type;
+};
+
+/**
+ * \ingroup ccnx
+ * \brief Typedef for MRU index of content store container
+ */
+struct CcnxContentStoreByMru
+{
+ typedef
+ CcnxContentStoreContainer::type::index<__ccnx_private::mru>::type
+ type;
+};
+
+#ifdef _DEBUG
+#define DUMP_INDEX_TAG ordered
+#define DUMP_INDEX CcnxContentStoreOrderedPrefix
+/**
+ * \ingroup ccnx
+ * \brief Typedef for ordered index of content store container
+ */
+struct CcnxContentStoreOrderedPrefix
+{
+ typedef
+ CcnxContentStoreContainer::type::index<__ccnx_private::ordered>::type
+ type;
+};
+#else
+#define DUMP_INDEX_TAG mru
+#define DUMP_INDEX CcnxContentStoreByMru
+#endif
+
+/**
+ * \ingroup ccnx
+ * \brief NDN content store entry
+ */
+class CcnxContentStore : public Object
+{
+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( );
+ virtual ~CcnxContentStore( );
- // Find corresponding CS entry for the given content name
- CsEntry* Lookup( const string prefix );
- //bool isValid( const CsIterator &it ) { return it!=_cs.end(); }
+ /**
+ * \brief Find corresponding CS entry for the given interest
+ *
+ * \param interest Interest for which matching content store entry
+ * will be searched
+ *
+ * If an entry is found, it is promoted to the top of most recent
+ * used entries index, \see m_contentStore
+ */
+ Ptr<Packet>
+ Lookup (Ptr<const CcnxInterestHeader> interest);
- // Add new content to the content store. Old content will be replaced
- void Add( const string contentName, int contentSize );
-
- // Dump content store entries
- void Dump( );
+ /**
+ * \brief Add a new content to the content store.
+ *
+ * \param header Fully parsed CcnxContentObjectHeader
+ * \param packet Fully formed CCNx packet to add to content store
+ * (will be copied and stripped down of headers)
+ *
+ * If entry with the same prefix exists, the old entry will be
+ * promoted to the top of the MRU hash
+ */
+ void
+ Add (Ptr<CcnxContentObjectHeader> header, Ptr<const Packet> packet);
+
+ /**
+ * \brief Set maximum size of content store
+ *
+ * \param size size in packets
+ */
+ inline void
+ SetMaxSize (uint32_t maxSize);
+
+ /**
+ * \brief Get maximum size of content store
+ *
+ * \returns size in packets
+ */
+ inline uint32_t
+ GetMaxSize () const;
+
+ /**
+ * \brief Print out content store entries
+ *
+ * Debug build provides dumping of content store entries in
+ * lexicographical order of corresponding prefixes
+ *
+ * Release build dumps everything in MRU order
+ */
+ void Print () const;
protected:
- //move the given CS entry to the head of the list
- void Promote( CsEntry &entry );
-
+ // /**
+ // * \brief Move the given CS entry to the head of the list
+ // *
+ // * \param entry Content Store entry
+ // */
+ // void Promote( CsEntry &entry );
+
+ /**
+ * \todo Alex: DoDispose and NotifyNewAggregate are seem to be very
+ * important, but I'm not yet sure what exactly they are supposed to
+ * do
+ */
+ // virtual void DoDispose ();
+ // virtual void NotifyNewAggregate ();
+
private:
- int m_maxSize; // maximum number of entries in cache
-
- string_key_hash_t<CsEntry> m_contentStore; // actual content store
- list<CsEntry*> m_LRU; // LRU index of the content store
- SystemMutex m_csMutex; // just to make sure we are not
+ CcnxContentStore (const CcnxContentStore &o); ///< Disabled copy constructor
+ CcnxContentStore& operator= (const CcnxContentStore &o); ///< Disabled copy operator
+
+private:
+ int m_maxSize; ///< \brief maximum number of entries in cache \internal
+ // string_key_hash_t<CsEntry> m_contentStore; ///< \brief actual content store \internal
+
+ /**
+ * \brief Content store implemented as a Boost.MultiIndex container
+ * \internal
+ */
+ CcnxContentStoreContainer::type m_contentStore;
};
+
+inline std::ostream&
+operator<< (std::ostream &os, const CcnxContentStore &cs)
+{
+ cs.Print ();
+ return os;
}
-#endif
+
+const Name::Components&
+CcnxContentStoreEntry::GetName () const
+{
+ return m_header->GetName ();
+}
+
+Ptr<const CcnxContentObjectHeader>
+CcnxContentStoreEntry::GetHeader () const
+{
+ return m_header;
+}
+
+Ptr<const Packet>
+CcnxContentStoreEntry::GetPacket () const
+{
+ return m_packet;
+}
+
+
+inline void
+CcnxContentStore::SetMaxSize (uint32_t maxSize)
+{
+ m_maxSize = maxSize;
+}
+
+inline uint32_t
+CcnxContentStore::GetMaxSize () const
+{
+ return m_maxSize;
+}
+
+} //namespace ns3
+
+#endif // CCNX_CONTENT_STORE_H
diff --git a/model/ccnx-face.cc b/model/ccnx-face.cc
index e19dc57..3250355 100644
--- a/model/ccnx-face.cc
+++ b/model/ccnx-face.cc
@@ -34,6 +34,7 @@
CcnxFace::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CcnxFace")
+ .SetGroupName ("Ccnx")
.SetParent<Object> ()
;
return tid;
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 6d4b045..7159109 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -28,6 +28,7 @@
TypeId CcnxForwardingStrategy::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CcnxForwardingStrategy")
+ .SetGroupName ("Ccnx")
.SetParent<Object> ()
;
return tid;
diff --git a/model/ccnx-interest-header.cc b/model/ccnx-interest-header.cc
index 02ad9af..330e2f4 100644
--- a/model/ccnx-interest-header.cc
+++ b/model/ccnx-interest-header.cc
@@ -40,6 +40,7 @@
CcnxInterestHeader::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CcnxInterestHeader")
+ .SetGroupName ("Ccnx")
.SetParent<Header> ()
.AddConstructor<CcnxInterestHeader> ()
;
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index ff3f926..8b7cccd 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -37,6 +37,7 @@
#include "ccnx-forwarding-strategy.h"
#include "ccnx-interest-header.h"
#include "ccnx-content-object-header.h"
+#include "ccnx-content-store.h"
#include <boost/foreach.hpp>
@@ -53,6 +54,7 @@
{
static TypeId tid = TypeId ("ns3::CcnxL3Protocol")
.SetParent<Ccnx> ()
+ .SetGroupName ("Ccnx")
.AddConstructor<CcnxL3Protocol> ()
// .AddTraceSource ("Tx", "Send ccnx packet to outgoing interface.",
// MakeTraceSourceAccessor (&CcnxL3Protocol::m_txTrace))
@@ -179,6 +181,12 @@
void
CcnxL3Protocol::Receive (const Ptr<CcnxFace> &face, const Ptr<const Packet> &p)
{
+ if (face->IsUp ())
+ {
+ NS_LOG_LOGIC ("Dropping received packet -- interface is down");
+ // m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), incomingFace);
+ return;
+ }
NS_LOG_LOGIC ("Packet from face " << &face << " received on node " << m_node->GetId ());
Ptr<Packet> packet = p->Copy (); // give upper layers a rw copy of the packet
@@ -198,16 +206,11 @@
const Ptr<CcnxInterestHeader> &header,
const Ptr<Packet> &packet)
{
- if (incomingFace->IsUp ())
- {
- NS_LOG_LOGIC ("Dropping received packet -- interface is down");
- // m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), incomingFace);
- return;
- }
-
- NS_LOG_LOGIC ("Receiving interest from " << incomingFace);
+ NS_LOG_LOGIC ("Receiving interest from " << &incomingFace);
// m_rxTrace (packet, m_node->GetObject<Ccnx> (), incomingFace);
+ /// \todo Processing of Interest packets
+
// NS_ASSERT_MSG (m_forwardingStrategy != 0, "Need a forwarding protocol object to process packets");
// if (!m_forwardingStrategy->RouteInput (packet, incomingFace,
// MakeCallback (&CcnxL3Protocol::Send, this),
@@ -224,14 +227,9 @@
const Ptr<CcnxContentObjectHeader> &header,
const Ptr<Packet> &packet)
{
- if (incomingFace->IsUp ())
- {
- NS_LOG_LOGIC ("Dropping received packet -- interface is down");
- // m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), incomingFace);
- return;
- }
+ NS_LOG_LOGIC ("Receiving contentObject from " << &incomingFace);
- NS_LOG_LOGIC ("Receiving contentObject from " << incomingFace);
+ /// \todo Processing of ContentObject packets
}
// fake method
@@ -245,27 +243,21 @@
void
CcnxL3Protocol::Send (const Ptr<CcnxFace> &face, const Ptr<Packet> &packet)
{
- // NS_LOG_FUNCTION (this << "packet: " << packet << ", route: "<< route);
-
- // if (route == 0)
- // {
- // NS_LOG_WARN ("No route to host. Drop.");
- // // m_dropTrace (packet, DROP_NO_ROUTE, m_node->GetObject<Ccnx> (), 0);
- // return;
- // }
- // Ptr<CcnxFace> outFace = route->GetOutputFace ();
+ NS_LOG_FUNCTION (this << "packet: " << &packet << ", face: "<< &face); //
- // if (outFace->IsUp ())
- // {
- // NS_LOG_LOGIC ("Sending via face " << *outFace);
- // // m_txTrace (packet, m_node->GetObject<Ccnx> (), outFace);
- // outFace->Send (packet);
- // }
- // else
- // {
- // NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << *outFace);
- // // m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), outFace);
- // }
+ NS_ASSERT_MSG (face != 0, "Face should never be NULL");
+
+ if (face->IsUp ())
+ {
+ NS_LOG_LOGIC ("Sending via face " << &face); //
+ m_txTrace (packet, m_node->GetObject<Ccnx> (), face);
+ face->Send (packet);
+ }
+ else
+ {
+ NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << &face);
+ m_dropTrace (packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ccnx> (), face);
+ }
}
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 145051f..6167fd0 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -41,7 +41,8 @@
class Header;
class CcnxInterestHeader;
class CcnxContentObjectHeader;
-
+class CcnxContentStore;
+
/**
* \ingroup ccnx
* \brief Actual implementation of the Ccnx network layer
@@ -160,15 +161,25 @@
Ptr<Node> m_node; ///< \brief node on which ccnx stack is installed
Ptr<CcnxForwardingStrategy> m_forwardingStrategy; ///< \brief smart pointer to the selected forwarding strategy
- // TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_sendOutgoingTrace;
- // TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_unicastForwardTrace;
- // TracedCallback<Ptr<const Packet>, Ptr<const CcnxFace> > m_localDeliverTrace;
+ Ptr<CcnxContentStore> m_contentStore;
+
+ /**
+ * \brief Trace of transmitted packets, including all headers
+ * \internal
+ */
+ TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_txTrace;
- // // The following two traces pass a packet with an IP header
- // TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_txTrace;
- // TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_rxTrace;
- // // <ip-header, payload, reason, ifindex> (ifindex not valid if reason is DROP_NO_ROUTE)
- // TracedCallback<Ptr<const Packet>, DropReason, Ptr<const Ccnx>, Ptr<const CcnxFace> > m_dropTrace;
+ /**
+ * \brief Trace of received packets, including all headers
+ * \internal
+ */
+ TracedCallback<Ptr<const Packet>, Ptr<Ccnx>, Ptr<const CcnxFace> > m_rxTrace;
+
+ /**
+ * \brief Trace of dropped packets, including reason and all headers
+ * \internal
+ */
+ TracedCallback<Ptr<const Packet>, DropReason, Ptr<const Ccnx>, Ptr<const CcnxFace> > m_dropTrace;
};
} // Namespace ns3
diff --git a/model/ccnx-local-face.cc b/model/ccnx-local-face.cc
index ea2a84b..80b0b52 100644
--- a/model/ccnx-local-face.cc
+++ b/model/ccnx-local-face.cc
@@ -37,6 +37,7 @@
CcnxLocalFace::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::CcnxLocalFace")
+ .SetGroupName ("Ccnx")
.SetParent<CcnxFace> ()
;
return tid;
diff --git a/model/ccnx-net-device-face.cc b/model/ccnx-net-device-face.cc
index b5816a4..9bdcd43 100644
--- a/model/ccnx-net-device-face.cc
+++ b/model/ccnx-net-device-face.cc
@@ -38,6 +38,7 @@
CcnxNetDeviceFace::GetTypeId ()
{
static TypeId tid = TypeId ("ns3::CcnxNetDeviceFace")
+ .SetGroupName ("Ccnx")
.SetParent<CcnxFace> ()
;
return tid;
diff --git a/model/ccnx.cc b/model/ccnx.cc
index a940c36..0fe4b31 100644
--- a/model/ccnx.cc
+++ b/model/ccnx.cc
@@ -32,6 +32,7 @@
Ccnx::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Ccnx")
+ .SetGroupName ("Ccnx")
.SetParent<Object> ()
;
return tid;
diff --git a/model/hash-helper.h b/model/hash-helper.h
index 880a217..36a9ee8 100644
--- a/model/hash-helper.h
+++ b/model/hash-helper.h
@@ -18,48 +18,50 @@
* Author: Ilya Moiseenko <iliamo@cs.ucla.edu>
*/
-#ifndef ccnx_hash_helper_h
-#define ccnx_hash_helper_h
+#ifndef CCNX_HASH_HELPER_H
+#define CCNX_HASH_HELPER_H
#include <string>
-#include <boost/unordered_map.hpp>
-#include <boost/functional/hash.hpp>
#include <boost/foreach.hpp>
+#include "name-components.h"
-//size of content store
-#define NDN_CONTENT_STORE_SIZE 100
-//maximum length of content name
-#define NDN_MAX_NAME_LENGTH 30
-
-//using namespace std;
-
-#define KEY(x) x->first
-#define VALUE(x) x->second
-
-
-/*template<typename T>
-struct hash : public std::unary_function<T, std::size_t> {
- std::size_t operator()(T const&) const;
-};*/
-
-struct string_hash : public std::unary_function<std::string, std::size_t>
+namespace ns3
{
- inline std::size_t operator( )( std::string str ) const
- {
- std::size_t hash = str.size() + 23;
- for( std::string::const_iterator it = str.begin( ); it!=str.end(); it++ )
- {
- hash = ((hash << 6) ^ (hash >> 27)) + static_cast<std::size_t>( *it );
- }
-
- return boost::hash_value(hash); //hash;
- }
-};
-// A collision-chaining hash table mapping strings to ints.
-template<typename Value>
-class string_key_hash_t : public boost::unordered_map<std::string,Value, string_hash, std::equal_to<std::string>,std::allocator<std::string> >
+/**
+ * \ingroup ccnx-helpers
+ * \brief Helper providing hash value for the name prefix
+ *
+ * The whole prefix is considered as a long string with '/' delimiters
+ *
+ * \todo Testing is required to determine if this hash function
+ * actually provides good hash results
+ */
+struct CcnxPrefixHash : public std::unary_function<Name::Components, std::size_t>
{
+ std::size_t
+ operator() (const Name::Components &prefix) const
+ {
+ std::size_t hash = 23;
+ BOOST_FOREACH (const std::string &str, prefix.GetComponents ())
+ {
+ hash += str.size ();
+ hash = ((hash << 6) ^ (hash >> 27)) + '/';
+ BOOST_FOREACH (char c, str)
+ {
+ hash = ((hash << 6) ^ (hash >> 27)) + c;
+ }
+ }
+ return hash;
+ }
};
+
+// // A collision-chaining hash table mapping strings to ints.
+// template<typename Value>
+// class string_key_hash_t : public boost::unordered_map<std::string,Value, string_hash, std::equal_to<std::string>,std::allocator<std::string> >
+// {
+// };
-#endif
\ No newline at end of file
+} // namespace ns3
+
+#endif // CCNX_HASH_HELPER_H
diff --git a/model/name-components.h b/model/name-components.h
index 0ea4821..95d2347 100644
--- a/model/name-components.h
+++ b/model/name-components.h
@@ -24,6 +24,7 @@
#include "ns3/simple-ref-count.h"
#include <string>
+#include <algorithm>
#include <list>
namespace ns3 {
@@ -58,6 +59,12 @@
inline size_t
size () const;
+
+ inline bool
+ operator== (const Components &prefix) const;
+
+ inline bool
+ operator< (const Components &prefix) const;
private:
std::list<std::string> m_prefix;
@@ -79,8 +86,20 @@
{
(*this) (s);
}
-
-
+
+bool
+Components::operator== (const Components &prefix) const
+{
+ return std::equal (m_prefix.begin (), m_prefix.end (), prefix.m_prefix.begin ());
+}
+
+bool
+Components::operator< (const Components &prefix) const
+{
+ return std::lexicographical_compare (m_prefix.begin (), m_prefix.end (),
+ prefix.m_prefix.begin (), prefix.m_prefix.end ());
+}
+
} // Namespace Name
} // namespace ns3