Initial redesign of internal data structures
diff --git a/model/ccnx-bestroute-strategy.cc b/model/ccnx-bestroute-strategy.cc
index e688cec..8fc6f1e 100644
--- a/model/ccnx-bestroute-strategy.cc
+++ b/model/ccnx-bestroute-strategy.cc
@@ -72,7 +72,7 @@
 
   int propagatedCount = 0;
 
-  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
+  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;
diff --git a/model/ccnx-content-store.cc b/model/ccnx-content-store.cc
index c5a66c9..ccbf200 100644
--- a/model/ccnx-content-store.cc
+++ b/model/ccnx-content-store.cc
@@ -43,6 +43,7 @@
 
     .AddTraceSource ("CacheHits", "Trace called every time there is a cache hit",
                      MakeTraceSourceAccessor (&CcnxContentStore::m_cacheHitsTrace))
+
     .AddTraceSource ("CacheMisses", "Trace called every time there is a cache miss",
                      MakeTraceSourceAccessor (&CcnxContentStore::m_cacheMissesTrace))
     ;
diff --git a/model/ccnx-content-store.h b/model/ccnx-content-store.h
index 07888e7..27bcda4 100644
--- a/model/ccnx-content-store.h
+++ b/model/ccnx-content-store.h
@@ -151,11 +151,6 @@
   
   /**
    * \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
    */
   virtual void
   Print () const = 0;
diff --git a/model/ccnx-fib.h b/model/ccnx-fib.h
index 7c2c6af..bbbc44f 100644
--- a/model/ccnx-fib.h
+++ b/model/ccnx-fib.h
@@ -271,6 +271,8 @@
 class CcnxFib : public Object
 {
 public:
+  typedef CcnxFibEntryContainer::type::iterator iterator;
+  
   /**
    * \brief Interface ID
    *
diff --git a/model/ccnx-flooding-strategy.cc b/model/ccnx-flooding-strategy.cc
index 290497e..3135afd 100644
--- a/model/ccnx-flooding-strategy.cc
+++ b/model/ccnx-flooding-strategy.cc
@@ -83,7 +83,7 @@
 
   int propagatedCount = 0;
 
-  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
+  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry->m_faces.get<i_metric> ())
     {
       NS_LOG_DEBUG ("Trying " << boost::cref(metricFace));
       if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED) // all non-read faces are in the front of the list
diff --git a/model/ccnx-forwarding-strategy.cc b/model/ccnx-forwarding-strategy.cc
index 93c3847..4983860 100644
--- a/model/ccnx-forwarding-strategy.cc
+++ b/model/ccnx-forwarding-strategy.cc
@@ -92,7 +92,7 @@
 
   int propagatedCount = 0;
   
-  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry.m_faces.get<i_metric> ())
+  BOOST_FOREACH (const CcnxFibFaceMetric &metricFace, pitEntry.m_fibEntry->m_faces.get<i_metric> ())
     {
       if (metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_RED ||
           metricFace.m_status == CcnxFibFaceMetric::NDN_FIB_YELLOW)
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index aa5be00..9abe297 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -182,8 +182,8 @@
 
       // If this face is the only for the associated FIB entry, then FIB entry will be removed soon.
       // Thus, we have to remove the whole PIT entry
-      if (pitEntry.m_fibEntry.m_faces.size () == 1 &&
-          pitEntry.m_fibEntry.m_faces.begin ()->m_face == face)
+      if (pitEntry.m_fibEntry->m_faces.size () == 1 &&
+          pitEntry.m_fibEntry->m_faces.begin ()->m_face == face)
         {
           entriesToRemoves.push_back (boost::cref (pitEntry));
         }
@@ -293,22 +293,18 @@
   NS_LOG_FUNCTION (incomingFace << header << packet);
   m_inNacks (header, incomingFace);
 
-  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> ();
-
-  if (isNew || !isDuplicated) // potential flow
+  CcnxPit::iterator pitEntry = m_pit->Lookup (*header);
+  if (pitEntry == m_pit->end ())
     {
       // somebody is doing something bad
       m_dropNacks (header, NON_DUPLICATED, incomingFace);
       return;
     }
   
-  // CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry.m_incoming.find (incomingFace);
-  CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry.m_outgoing.find (incomingFace);
+  // CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry->m_incoming.find (incomingFace);
+  CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry->m_outgoing.find (incomingFace);
 
-  if (outFace == pitEntry.m_outgoing.end ())
+  if (outFace == pitEntry->m_outgoing.end ())
     {
 //      NS_ASSERT_MSG (false,
 //                     "Node " << GetObject<Node> ()->GetId () << ", outgoing entry should exist for face " << boost::cref(*incomingFace) << "\n" <<
@@ -325,7 +321,7 @@
 
   NS_LOG_ERROR ("Nack on " << boost::cref(*incomingFace));
 
-  m_pit->modify (m_pit->iterator_to (pitEntry),
+  m_pit->modify (pitEntry,
                  ll::bind (&CcnxPitEntry::SetWaitingInVain, ll::_1, outFace));
 
   // If NACK is NACK_GIVEUP_PIT, then neighbor gave up trying to and removed it's PIT entry.
@@ -333,22 +329,22 @@
 
   if (header->GetNack () == CcnxInterestHeader::NACK_GIVEUP_PIT)
     {
-      m_pit->modify (m_pit->iterator_to (pitEntry),
+      m_pit->modify (pitEntry,
                      ll::bind (&CcnxPitEntry::RemoveIncoming, ll::_1, incomingFace));
     }
 
-  m_fib->m_fib.modify (m_fib->m_fib.iterator_to (pitEntry.m_fibEntry),
+  m_fib->m_fib.modify (pitEntry->m_fibEntry,
                        ll::bind (&CcnxFibEntry::UpdateStatus,
                                  ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
 
-  if (pitEntry.m_incoming.size () == 0) // interest was actually satisfied
+  if (pitEntry->m_incoming.size () == 0) // interest was actually satisfied
     {
       // no need to do anything
       m_dropNacks (header, AFTER_SATISFIED, incomingFace);
       return;
     }
 
-  if (!pitEntry.AreAllOutgoingInVain ()) // not all ougtoing are in vain
+  if (!pitEntry->AreAllOutgoingInVain ()) // not all ougtoing are in vain
     {
       NS_LOG_DEBUG ("Not all outgoing are in vain");
       // suppress
@@ -362,7 +358,7 @@
   nonNackInterest->AddHeader (*header);
   
   bool propagated = m_forwardingStrategy->
-    PropagateInterest (pitEntry, incomingFace, header, nonNackInterest);
+    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
@@ -383,15 +379,22 @@
                                  const Ptr<const Packet> &packet)
 {
   m_inInterests (header, incomingFace);
-  // NS_LOG_DEBUG (*m_pit);
 
-  // Lookup of Pit (and associated Fib) entry for this Interest 
-  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> ();
+  CcnxPit::iterator pitEntry = m_pit->Lookup (*header);
+  if (pitEntry == m_pit->end ())
+    {
+      pitEntry = m_pit->Create (*header);
+    }
 
-  // NS_LOG_DEBUG ("isNew: " << isNew << ", isDup: " << isDuplicated);
+  if (pitEntry == m_pit->end ())
+    {
+      // if it is still not created, then give up processing
+      m_dropInterests (header, PIT_LIMIT, incomingFace);
+      return;
+    }
+  
+  bool isNew = pitEntry->m_incoming.size () == 0 && pitEntry->m_outgoing.size () == 0;
+  bool isDuplicated = m_pit->CheckIfDuplicate (pitEntry, *header);
   
   NS_LOG_FUNCTION (header->GetName () << header->GetNonce () << boost::cref (*incomingFace) << isDuplicated);
 
@@ -406,12 +409,12 @@
   /////////////////////////////////////////////////////////////////////////////////////////
   
   // Data is not in cache
-  CcnxPitEntryIncomingFaceContainer::type::iterator inFace = pitEntry.m_incoming.find (incomingFace);
-  CcnxPitEntryOutgoingFaceContainer::type::iterator outFace = pitEntry.m_outgoing.find (incomingFace);
+  CcnxPitEntry::in_iterator inFace   = pitEntry->m_incoming.find (incomingFace);
+  CcnxPitEntry::out_iterator outFace = pitEntry->m_outgoing.find (incomingFace);
 
   bool isRetransmitted = false;
   
-  if (inFace != pitEntry.m_incoming.end ())
+  if (inFace != pitEntry->m_incoming.end ())
     {
       // CcnxPitEntryIncomingFace.m_arrivalTime keeps track arrival time of the first packet... why?
 
@@ -420,7 +423,7 @@
     }
   else
     {
-      m_pit->modify (m_pit->iterator_to (pitEntry),
+      m_pit->modify (pitEntry,
                      ll::var(inFace) = ll::bind (&CcnxPitEntry::AddIncoming, ll::_1, incomingFace));
     }
   //////////////////////////////////////////////////////////////////////////////////
@@ -466,11 +469,11 @@
     }
 
   // update PIT entry lifetime
-  m_pit->modify (m_pit->iterator_to (pitEntry),
+  m_pit->modify (pitEntry,
                  ll::bind (&CcnxPitEntry::UpdateLifetime, ll::_1,
                            header->GetInterestLifetime ()));
   
-  if (outFace != pitEntry.m_outgoing.end ())
+  if (outFace != pitEntry->m_outgoing.end ())
     {
       NS_LOG_DEBUG ("Non duplicate interests from the face we have sent interest to. Don't suppress");
       // got a non-duplicate interest from the face we have sent interest to
@@ -481,7 +484,7 @@
 
       // ?? not sure if we need to do that ?? ...
       
-      m_fib->m_fib.modify(m_fib->m_fib.iterator_to (pitEntry.m_fibEntry),
+      m_fib->m_fib.modify(pitEntry->m_fibEntry,
                           ll::bind (&CcnxFibEntry::UpdateStatus,
                                     ll::_1, incomingFace, CcnxFibFaceMetric::NDN_FIB_YELLOW));
     }
@@ -499,17 +502,17 @@
   /////////////////////////////////////////////////////////////////////
   
   bool propagated = m_forwardingStrategy->
-    PropagateInterest (pitEntry, incomingFace, header, packet);
+    PropagateInterest (*pitEntry, incomingFace, header, packet);
 
   if (!propagated && isRetransmitted) //give another chance if retransmitted
     {
       // increase max number of allowed retransmissions
-      m_pit->modify (m_pit->iterator_to (pitEntry),
+      m_pit->modify (pitEntry,
                      ll::bind (&CcnxPitEntry::IncreaseAllowedRetxCount, ll::_1));
 
       // try again
       propagated = m_forwardingStrategy->
-        PropagateInterest (pitEntry, incomingFace, header, packet);
+        PropagateInterest (*pitEntry, incomingFace, header, packet);
     }
   
   // ForwardingStrategy will try its best to forward packet to at least one interface.
@@ -529,10 +532,9 @@
                                const Ptr<const Packet> &packet)
 {
   // 1. Lookup PIT entry
-  try
+  CcnxPit::iterator pitEntry = m_pit->Lookup (*header);
+  if (pitEntry != m_pit->end ())
     {
-      CcnxPitEntryContainer::type::iterator pitEntry = m_pit->Lookup (*header);
-      
       //satisfy all pending incoming Interests
       BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry->m_incoming)
         {
@@ -554,12 +556,10 @@
                          ll::bind (&CcnxPitEntry::ClearOutgoing, ll::_1));
           
           // Set pruning timout on PIT entry (instead of deleting the record)
-          m_pit->modify (pitEntry,
-                         ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
-                                   Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+          m_pit->MarkErased (pitEntry);
         }
     }
-  catch (CcnxPitEntryNotFound)
+  else
     {
       NS_LOG_DEBUG ("Pit entry not found (was satisfied and removed before)");
       return; // do not process unsoliced data packets
@@ -576,21 +576,19 @@
     
   NS_LOG_FUNCTION (incomingFace << header->GetName () << payload << packet);
   m_inData (header, payload, incomingFace);
-  // NS_LOG_DEBUG (*m_pit);
   
   // 1. Lookup PIT entry
-  try
+  CcnxPit::iterator pitEntry = m_pit->Lookup (*header);
+  if (pitEntry != m_pit->end ())
     {
-      CcnxPitEntryContainer::type::iterator pitEntry = m_pit->Lookup (*header);
-
       // Note that with MultiIndex we need to modify entries indirectly
 
-      CcnxPitEntryOutgoingFaceContainer::type::iterator out = pitEntry->m_outgoing.find (incomingFace);
+      CcnxPitEntry::out_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_fib->m_fib.modify (m_fib->m_fib.iterator_to (pitEntry->m_fibEntry),
+          m_fib->m_fib.modify (pitEntry->m_fibEntry,
                                ll::bind (&CcnxFibEntry::UpdateFaceRtt,
                                          ll::_1,
                                          incomingFace,
@@ -617,7 +615,7 @@
         }
 
       // Update metric status for the incoming interface in the corresponding FIB entry
-      m_fib->m_fib.modify (m_fib->m_fib.iterator_to (pitEntry->m_fibEntry),
+      m_fib->m_fib.modify (pitEntry->m_fibEntry,
                            ll::bind (&CcnxFibEntry::UpdateStatus, ll::_1,
                                      incomingFace, CcnxFibFaceMetric::NDN_FIB_GREEN));
   
@@ -630,16 +628,14 @@
       if (pitEntry->m_incoming.size () == 0)
         {
           // Set pruning timout on PIT entry (instead of deleting the record)
-          m_pit->modify (pitEntry,
-                         ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
-                                   Simulator::Now () + m_pit->GetPitEntryPruningTimeout ()));
+          m_pit->MarkErased (pitEntry);
         }
       else
         {
           OnDataDelayed (header, payload, packet);
         }
     }
-  catch (CcnxPitEntryNotFound)
+  else
     {
       NS_LOG_DEBUG ("Pit entry not found");
       if (m_cacheUnsolicitedData)
@@ -660,18 +656,18 @@
 }
 
 void
-CcnxL3Protocol::GiveUpInterest (const CcnxPitEntry &pitEntry,
+CcnxL3Protocol::GiveUpInterest (CcnxPit::iterator pitEntry,
                                 Ptr<CcnxInterestHeader> header)
 {
-  NS_LOG_FUNCTION (this << &pitEntry);
-  // NS_LOG_DEBUG (*m_pit);
+  NS_LOG_FUNCTION (this);
+
   if (m_nacksEnabled)
     {
       Ptr<Packet> packet = Create<Packet> ();
       header->SetNack (CcnxInterestHeader::NACK_GIVEUP_PIT);
       packet->AddHeader (*header);
 
-      BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry.m_incoming)
+      BOOST_FOREACH (const CcnxPitEntryIncomingFace &incoming, pitEntry->m_incoming)
         {
           NS_LOG_DEBUG ("Send NACK for " << boost::cref (header->GetName ()) << " to " << boost::cref (*incoming.m_face));
           incoming.m_face->Send (packet->Copy ());
@@ -680,17 +676,15 @@
         }
   
       // All incoming interests cannot be satisfied. Remove them
-      m_pit->modify (m_pit->iterator_to (pitEntry),
+      m_pit->modify (pitEntry,
                      ll::bind (&CcnxPitEntry::ClearIncoming, ll::_1));
 
       // Remove also outgoing
-      m_pit->modify (m_pit->iterator_to (pitEntry),
+      m_pit->modify (pitEntry,
                      ll::bind (&CcnxPitEntry::ClearOutgoing, 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 ()));
+      m_pit->MarkErased (pitEntry);
     }
 }
 
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index 1d5a3af..4d01da2 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -160,20 +160,8 @@
   CcnxL3Protocol(const CcnxL3Protocol &); ///< copy constructor is disabled
   CcnxL3Protocol &operator = (const CcnxL3Protocol &); ///< copy operator is disabled
 
-  // /// \brief Set buckets leak interval
-  // void
-  // SetBucketLeakInterval (Time interval);
-
-  // /// \brief Get buckets leak interval
-  // Time
-  // GetBucketLeakInterval () const;
-  
-  // /// \brief Periodically generate pre-calculated number of tokens (leak buckets)
-  // void
-  // LeakBuckets ();
-
   void
-  GiveUpInterest (const CcnxPitEntry &pitEntry,
+  GiveUpInterest (CcnxPit::iterator pitEntry,
                   Ptr<CcnxInterestHeader> header);
 
   void
diff --git a/model/ccnx-pit-entry.cc b/model/ccnx-pit-entry.cc
index 9c8c389..127b589 100644
--- a/model/ccnx-pit-entry.cc
+++ b/model/ccnx-pit-entry.cc
@@ -36,12 +36,10 @@
 
 CcnxPitEntry::CcnxPitEntry (Ptr<CcnxNameComponents> prefix,
                             const Time &expireTime,
-                            const CcnxFibEntry &fibEntry)
+                            CcnxFib::iterator fibEntry)
   : m_prefix (prefix)
   , m_fibEntry (fibEntry)
   , m_expireTime (Simulator::Now () + expireTime)
-  // , m_timerExpired (false)
-  // , m_counterExpirations (0)
   , m_maxRetxCount (0)
 {
 }
@@ -53,7 +51,6 @@
   m_expireTime = expireTime;
 }
 
-
 void
 CcnxPitEntry::UpdateLifetime (const Time &offsetTime)
 {
@@ -66,10 +63,10 @@
   NS_LOG_INFO ("Updated lifetime to " << m_expireTime.ToDouble (Time::S));
 }
 
-CcnxPitEntryIncomingFaceContainer::type::iterator
+CcnxPitEntry::in_iterator
 CcnxPitEntry::AddIncoming (Ptr<CcnxFace> face)
 {
-  std::pair<CcnxPitEntryIncomingFaceContainer::type::iterator,bool> ret = 
+  std::pair<in_iterator,bool> ret = 
     m_incoming.insert (CcnxPitEntryIncomingFace (face));
 
   NS_ASSERT_MSG (ret.second, "Something is wrong");
@@ -84,10 +81,10 @@
 }
 
 
-CcnxPitEntryOutgoingFaceContainer::type::iterator
+CcnxPitEntry::out_iterator
 CcnxPitEntry::AddOutgoing (Ptr<CcnxFace> face)
 {
-  std::pair<CcnxPitEntryOutgoingFaceContainer::type::iterator,bool> ret =
+  std::pair<out_iterator,bool> ret =
     m_outgoing.insert (CcnxPitEntryOutgoingFace (face));
 
   if (!ret.second)
@@ -102,13 +99,12 @@
 void
 CcnxPitEntry::RemoveAllReferencesToFace (Ptr<CcnxFace> face)
 {
-  CcnxPitEntryIncomingFaceContainer::type::iterator incoming =
-    m_incoming.find (face);
+  in_iterator incoming = m_incoming.find (face);
 
   if (incoming != m_incoming.end ())
     m_incoming.erase (incoming);
 
-  CcnxPitEntryOutgoingFaceContainer::type::iterator outgoing =
+  out_iterator outgoing =
     m_outgoing.find (face);
 
   if (outgoing != m_outgoing.end ())
@@ -116,7 +112,7 @@
 }
 
 void
-CcnxPitEntry::SetWaitingInVain (CcnxPitEntryOutgoingFaceContainer::type::iterator face)
+CcnxPitEntry::SetWaitingInVain (CcnxPitEntry::out_iterator face)
 {
   NS_LOG_DEBUG (boost::cref (*face->m_face));
 
diff --git a/model/ccnx-pit-entry.h b/model/ccnx-pit-entry.h
index 6c69f99..bc81c89 100644
--- a/model/ccnx-pit-entry.h
+++ b/model/ccnx-pit-entry.h
@@ -52,29 +52,6 @@
 
 /**
  * \ingroup ccnx
- * \brief Typedef for indexed face container of CcnxPitEntryIncomingFace
- *
- * Indexes:
- * - by face (may be it will be possible to replace with just the std::map)
- */
-struct CcnxPitEntryIncomingFaceContainer
-{
-  /// @cond include_hidden
-  typedef boost::multi_index::multi_index_container<
-    CcnxPitEntryIncomingFace,
-    boost::multi_index::indexed_by<
-      // For fast access to elements using CcnxFace
-      boost::multi_index::ordered_unique<
-        boost::multi_index::tag<__ccnx_private::i_face>,
-        boost::multi_index::member<CcnxPitEntryIncomingFace, Ptr<CcnxFace>, &CcnxPitEntryIncomingFace::m_face>
-      >
-    >
-   > type;
-  /// @endcond
-};
-
-/**
- * \ingroup ccnx
  * \brief Typedef for indexed face container of CcnxPitEntryOutgoingFace
  *
  * Indexes:
@@ -108,13 +85,21 @@
 struct CcnxPitEntry
 {
 public:
+  typedef std::set< CcnxPitEntryIncomingFace > in_container; ///< @brief incoming faces container type
+  typedef in_container::iterator in_iterator;                ///< @brief iterator to incoming faces
+
+  typedef CcnxPitEntryOutgoingFaceContainer::type out_container; ///< @brief outgoing faces container type
+  typedef out_container::iterator out_iterator;              ///< @brief iterator to outgoing faces
+
+  typedef std::set< uint32_t > nonce_container;  ///< @brief nonce container type
+  
   /**
    * \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 &offsetTime, const CcnxFibEntry &fibEntry);
+  CcnxPitEntry (Ptr<CcnxNameComponents> prefix, const Time &offsetTime, CcnxFib::iterator fibEntry);
   
   /**
    * @brief Update lifetime of PIT entry
@@ -177,7 +162,7 @@
    * @param face Face to add to the list of incoming faces
    * @returns iterator to the added entry
    */
-  CcnxPitEntryIncomingFaceContainer::type::iterator
+  in_iterator
   AddIncoming (Ptr<CcnxFace> face);
 
   /**
@@ -199,7 +184,7 @@
    * @param face Face to add to the list of outgoing faces
    * @returns iterator to the added entry
    */
-  CcnxPitEntryOutgoingFaceContainer::type::iterator
+  out_iterator
   AddOutgoing (Ptr<CcnxFace> face);
 
   /**
@@ -222,7 +207,7 @@
    * @brief Flag outgoing face as hopeless
    */
   void
-  SetWaitingInVain (CcnxPitEntryOutgoingFaceContainer::type::iterator face);
+  SetWaitingInVain (out_iterator face);
   
   /**
    * @brief Check if all outgoing faces are NACKed
@@ -250,15 +235,15 @@
   /**
    * \brief Default constructor
    */
-  CcnxPitEntry () : m_fibEntry(*((CcnxFibEntry*)0)) {};
+  CcnxPitEntry () {};
   
 public:
   Ptr<CcnxNameComponents> m_prefix; ///< \brief Prefix of the PIT entry
-  const CcnxFibEntry &m_fibEntry; ///< \brief FIB entry related to this prefix
-  std::set<uint32_t> m_seenNonces; ///< \brief map of nonces that were seen for this prefix
+  CcnxFib::iterator m_fibEntry;     ///< \brief FIB entry related to this prefix
   
-  CcnxPitEntryIncomingFaceContainer::type m_incoming; ///< \brief container for incoming interests
-  CcnxPitEntryOutgoingFaceContainer::type m_outgoing; ///< \brief container for outgoing interests
+  nonce_container m_seenNonces;  ///< \brief map of nonces that were seen for this prefix  
+  in_container  m_incoming;      ///< \brief container for incoming interests
+  out_container m_outgoing;      ///< \brief container for outgoing interests
 
   Time m_expireTime;         ///< \brief Time when PIT entry will be removed
 
diff --git a/model/ccnx-pit.cc b/model/ccnx-pit.cc
index 4186af4..4824bb1 100644
--- a/model/ccnx-pit.cc
+++ b/model/ccnx-pit.cc
@@ -26,13 +26,14 @@
 #include "ccnx-interest-header.h"
 #include "ccnx-content-object-header.h"
 
-#include <boost/bind.hpp>
+#include <boost/lambda/bind.hpp>
 #include <boost/lambda/lambda.hpp>
 
 NS_LOG_COMPONENT_DEFINE ("CcnxPit");
 
 using namespace boost::tuples;
 using namespace boost;
+namespace ll = boost::lambda;
 
 namespace ns3 {
 
@@ -121,7 +122,7 @@
 
 void CcnxPit::CleanExpired ()
 {
-  NS_LOG_LOGIC ("Cleaning PIT. Total: " << size ());
+  // NS_LOG_LOGIC ("Cleaning PIT. Total: " << size ());
   Time now = Simulator::Now ();
 
   // uint32_t count = 0;
@@ -137,19 +138,15 @@
         break; // nothing else to do. All later records will not be stale
     }
 
-  // NS_LOG_LOGIC ("Cleaned " << count << " records. Total: " << size ());
-  // schedule next even
-  
+  // schedule next event  
   m_cleanupEvent = Simulator::Schedule (m_cleanupTimeout,
                                         &CcnxPit::CleanExpired, this); 
 }
 
-CcnxPitEntryContainer::type::iterator
+CcnxPit::iterator
 CcnxPit::Lookup (const CcnxContentObjectHeader &header) const
 {
-  // NS_LOG_FUNCTION_NOARGS ();
-
-  CcnxPitEntryContainer::type::iterator entry = end ();
+  iterator entry = end ();
 
   // do the longest prefix match
   const CcnxNameComponents &name = header.GetName ();
@@ -163,69 +160,70 @@
       if (entry != end())
         return entry;
     }
-  
-  throw CcnxPitEntryNotFound();
+
+  return end ();
 }
 
-boost::tuple<const CcnxPitEntry&, bool, bool>
+CcnxPit::iterator
 CcnxPit::Lookup (const CcnxInterestHeader &header)
 {
   NS_LOG_FUNCTION (header.GetName ());
   NS_ASSERT_MSG (m_fib != 0, "FIB should be set");
 
-  bool isDuplicate = false;
-  bool isNew = true;
-
-  CcnxPitEntryContainer::type::iterator entry =
-    get<i_prefix> ().find (header.GetName ());
-
+  iterator entry = get<i_prefix> ().find (header.GetName ());
   if (entry == end ())
-    {
-      if (m_maxSize > 0 &&
-          size () >= m_maxSize)
-        {
-          // remove old record
-          get<i_timestamp> ().erase (get<i_timestamp> ().begin ());
-        }
-      
-      CcnxFibEntryContainer::type::iterator fibEntry = m_fib->LongestPrefixMatch (header);
-      NS_ASSERT_MSG (fibEntry != m_fib->m_fib.end (),
-                     "There should be at least default route set" << " Prefix = "<<header.GetName() << "NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
+    return end ();
+   
+  return entry;
+}
 
-      entry = insert (end (),
-                      CcnxPitEntry (Create<CcnxNameComponents> (header.GetName ()),
-                                    header.GetInterestLifetime ().IsZero ()?m_PitEntryDefaultLifetime
-                                    :                                       header.GetInterestLifetime (),
-                                    *fibEntry));
-
-      // isDuplicate = false; // redundant
-      // isNew = true; // also redundant
-    }
-  else
-    {
-      NS_LOG_INFO ("ExpireTime: " << entry->m_expireTime.ToDouble (Time::S));
-      if (entry->m_expireTime - Simulator::Now () < MilliSeconds (10))
-        {
-          modify (entry,
-                  boost::bind(&CcnxPitEntry::ClearIncoming, boost::lambda::_1));
-          
-          modify (entry,
-                  boost::bind(&CcnxPitEntry::ClearOutgoing, boost::lambda::_1));
-        }
-      
-      isNew = entry->m_incoming.size () == 0 && entry->m_outgoing.size () == 0; // entry was preserved to detect loops, but technically removed
-      isDuplicate = entry->IsNonceSeen (header.GetNonce ());
-    }
-
-  if (!isDuplicate)
+bool
+CcnxPit::CheckIfDuplicate (CcnxPit::iterator entry, const CcnxInterestHeader &header)
+{
+  if (!entry->IsNonceSeen (header.GetNonce ()))
     {
       modify (entry,
-              boost::bind(&CcnxPitEntry::AddSeenNonce, boost::lambda::_1, header.GetNonce ()));
+              boost::bind(&CcnxPitEntry::AddSeenNonce, ll::_1, header.GetNonce ()));
+      return false;
     }
-
-  return make_tuple (cref(*entry), isNew, isDuplicate);
+  else
+    return true;
 }
 
+CcnxPit::iterator
+CcnxPit::Create (const CcnxInterestHeader &header)
+{
+  NS_ASSERT_MSG (get<i_prefix> ().find (header.GetName ()) == end (),
+                 "Entry already exists, Create must not be called!!!");
+  
+  if (m_maxSize > 0 &&
+      size () >= m_maxSize)
+    {
+      // remove old record
+      get<i_timestamp> ().erase (get<i_timestamp> ().begin ());
+    }
+      
+  CcnxFib::iterator fibEntry = m_fib->LongestPrefixMatch (header);
+  // NS_ASSERT_MSG (fibEntry != m_fib->m_fib.end (),
+  //                "There should be at least default route set" << " Prefix = "<<header.GetName() << "NodeID == " << m_fib->GetObject<Node>()->GetId() << "\n" << *m_fib);
+
+  return insert (end (),
+                 CcnxPitEntry (ns3::Create<CcnxNameComponents> (header.GetName ()),
+                               header.GetInterestLifetime ().IsZero ()?m_PitEntryDefaultLifetime
+                               :                                       header.GetInterestLifetime (),
+                               fibEntry));
+}
+
+
+void
+CcnxPit::MarkErased (CcnxPit::iterator entry)
+{
+  modify (entry,
+          ll::bind (&CcnxPitEntry::SetExpireTime, ll::_1,
+                    Simulator::Now () + m_PitEntryPruningTimout));
+}
+
+
 std::ostream& operator<< (std::ostream& os, const CcnxPit &pit)
 {
   BOOST_FOREACH (const CcnxPitEntry &entry, pit)
diff --git a/model/ccnx-pit.h b/model/ccnx-pit.h
index 826f49f..be9c80f 100644
--- a/model/ccnx-pit.h
+++ b/model/ccnx-pit.h
@@ -124,32 +124,50 @@
   /**
    * \brief Find corresponding PIT entry for the given content name
    * \param prefix Prefix for which to lookup the entry
-   * \returns const reference to Pit entry. If record not found,
-   *          CcnxPitEntryNotFound exception will be thrown
+   * \returns iterator to Pit entry. If record not found,
+   *          return end() iterator
    */
-  CcnxPitEntryContainer::type::iterator
+  iterator
   Lookup (const CcnxContentObjectHeader &header) const;
 
   /**
-   * \brief Find corresponding PIT entry for the given content name
-   * \param prefix Prefix for which to lookup the entry
-   * \returns a tuple:
-   * get<0>: `const CcnxPitEntry&`: a valid PIT entry (if record does not exist, it will be created)
-   * get<1>: `bool`: true if a new entry was created
-   * get<2>: `bool`: true if a PIT entry exists and Nonce that present in header has been already seen
-   * 
+   * \brief Find a PIT entry for the given content interest
+   * \param header parsed interest header
+   * \returns iterator to Pit entry. If record not found,
+   *          return end() iterator
    */
-  boost::tuple<const CcnxPitEntry&, bool, bool>
+  iterator
   Lookup (const CcnxInterestHeader &header);
 
   /**
-   * @brief Get pruning timeout for PIT entries (configuration parameter)
+   * @brief Check if the Interest carries an existent nonce.
+   * If not, nonce will be added to the list of known nonces
+   * @returns true if interest is duplicate (carries an existent nonce), false otherwise
    */
-  Time GetPitEntryPruningTimeout () const
-  {
-    return m_PitEntryPruningTimout;
-  }
+  bool
+  CheckIfDuplicate (iterator entry, const CcnxInterestHeader &header);
   
+  /**
+   * @brief Creates a PIT entry for the given interest
+   * @param header parsed interest header
+   * @returns iterator to Pit entry. If record could not be created (e.g., limit reached),
+   *          return end() iterator
+   *
+   * Note. This call assumes that the entry does not exist (i.e., there was a Lookup call before)
+   */
+  iterator
+  Create (const CcnxInterestHeader &header);
+  
+  /**
+   * @brief Mark PIT entry deleted
+   * @param entry PIT entry
+   *
+   * Effectively, this method removes all incoming/outgoing faces and set
+   * lifetime +m_PitEntryDefaultLifetime from Now ()
+   */
+  void
+  MarkErased (iterator entry);
+    
 protected:
   // inherited from Object class                                                                                                                                                        
   virtual void NotifyNewAggregate (); ///< @brief Even when object is aggregated to another Object
@@ -195,11 +213,6 @@
 
 std::ostream& operator<< (std::ostream& os, const CcnxPit &pit);
 
-/**
- * @brief Class for exception when PIT entry is not found
- */
-class CcnxPitEntryNotFound {};
-
 } // namespace ns3
 
 #endif	/* CCNX_PIT_H */
diff --git a/model/ccnx.h b/model/ccnx.h
index 41e950a..573a567 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -142,7 +142,8 @@
       NO_FACES,    // Interests
       NON_DUPLICATED, // Nacks
       AFTER_SATISFIED, // Nacks
-      UNSOLICITED      // data
+      UNSOLICITED,      // data
+      PIT_LIMIT         // PIT limit reached
     };
   
 protected: