Start of serious reorganization

The whole forwarding logic is (will be) moved to the Forwarding Strategy
class.
diff --git a/model/fib/ccnx-fib-entry.cc b/model/fib/ccnx-fib-entry.cc
new file mode 100644
index 0000000..c0c575a
--- /dev/null
+++ b/model/fib/ccnx-fib-entry.cc
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnx-fib-entry.h"
+
+#include "ns3/ccnx-name-components.h"
+#include "ns3/log.h"
+
+#define NDN_RTO_ALPHA 0.125
+#define NDN_RTO_BETA 0.25
+#define NDN_RTO_K 4
+
+#include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
+
+NS_LOG_COMPONENT_DEFINE ("CcnxFibEntry");
+
+namespace ns3
+{
+
+//////////////////////////////////////////////////////////////////////
+// Helpers
+//////////////////////////////////////////////////////////////////////
+namespace __ccnx_private {
+
+struct CcnxFibFaceMetricByFace
+{
+  typedef CcnxFibFaceMetricContainer::type::index<i_face>::type
+  type;
+};
+
+}
+//////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////
+
+using namespace __ccnx_private;
+
+void
+CcnxFibFaceMetric::UpdateRtt (const Time &rttSample)
+{
+  // const Time & this->m_rttSample
+  
+  //update srtt and rttvar (RFC 2988)
+  if (m_sRtt.IsZero ())
+    {
+      //first RTT measurement
+      NS_ASSERT_MSG (m_rttVar.IsZero (), "SRTT is zero, but variation is not");
+      
+      m_sRtt = rttSample;
+      m_rttVar = Time (m_sRtt / 2.0);
+    }
+  else
+    {
+      m_rttVar = Time ((1 - NDN_RTO_BETA) * m_rttVar + NDN_RTO_BETA * Abs(m_sRtt - rttSample));
+      m_sRtt = Time ((1 - NDN_RTO_ALPHA) * m_sRtt + NDN_RTO_ALPHA * rttSample);
+    }
+}
+
+/////////////////////////////////////////////////////////////////////
+
+void
+CcnxFibEntry::UpdateFaceRtt (Ptr<CcnxFace> face, const Time &sample)
+{
+  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,
+                  ll::bind (&CcnxFibFaceMetric::UpdateRtt, ll::_1, sample));
+
+  // reordering random access index same way as by metric index
+  m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
+}
+
+void
+CcnxFibEntry::UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status)
+{
+  NS_LOG_FUNCTION (this << boost::cref(*face) << 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,
+                  (&ll::_1)->*&CcnxFibFaceMetric::m_status = status);
+
+  // reordering random access index same way as by metric index
+  m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
+}
+
+void
+CcnxFibEntry::AddOrUpdateRoutingMetric (Ptr<CcnxFace> face, int32_t metric)
+{
+  NS_LOG_FUNCTION (this);
+  NS_ASSERT_MSG (face != NULL, "Trying to Add or Update NULL face");
+
+  CcnxFibFaceMetricByFace::type::iterator record = m_faces.get<i_face> ().find (face);
+  if (record == m_faces.get<i_face> ().end ())
+    {
+      m_faces.insert (CcnxFibFaceMetric (face, metric));
+    }
+  else
+  {
+    // don't update metric to higher value
+    if (record->m_routingCost > metric || record->m_status == CcnxFibFaceMetric::NDN_FIB_RED)
+      {
+        m_faces.modify (record,
+                        (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = metric);
+
+        m_faces.modify (record,
+                        (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_YELLOW);
+      }
+  }
+  
+  // reordering random access index same way as by metric index
+  m_faces.get<i_nth> ().rearrange (m_faces.get<i_metric> ().begin ());
+}
+
+void
+CcnxFibEntry::Invalidate ()
+{
+  for (CcnxFibFaceMetricByFace::type::iterator face = m_faces.begin ();
+       face != m_faces.end ();
+       face++)
+    {
+      m_faces.modify (face,
+                      (&ll::_1)->*&CcnxFibFaceMetric::m_routingCost = std::numeric_limits<uint16_t>::max ());
+
+      m_faces.modify (face,
+                      (&ll::_1)->*&CcnxFibFaceMetric::m_status = CcnxFibFaceMetric::NDN_FIB_RED);
+    }
+}
+
+const CcnxFibFaceMetric &
+CcnxFibEntry::FindBestCandidate (uint32_t skip/* = 0*/) const
+{
+  if (m_faces.size () == 0) throw CcnxFibEntry::NoFaces ();
+  skip = skip % m_faces.size();
+  return m_faces.get<i_nth> () [skip];
+}
+
+std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry)
+{
+  for (CcnxFibFaceMetricContainer::type::index<i_nth>::type::iterator metric =
+         entry.m_faces.get<i_nth> ().begin ();
+       metric != entry.m_faces.get<i_nth> ().end ();
+       metric++)
+    {
+      if (metric != entry.m_faces.get<i_nth> ().begin ())
+        os << ", ";
+
+      os << *metric;
+    }
+  return os;
+}
+
+std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric)
+{
+  static const std::string statusString[] = {"","g","y","r"};
+
+  os << *metric.m_face << "(" << metric.m_routingCost << ","<< statusString [metric.m_status] << "," << metric.m_face->GetMetric () << ")";
+  return os;
+}
+
+
+} // ns3
diff --git a/model/fib/ccnx-fib-entry.h b/model/fib/ccnx-fib-entry.h
new file mode 100644
index 0000000..9aa75cb
--- /dev/null
+++ b/model/fib/ccnx-fib-entry.h
@@ -0,0 +1,237 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef _CCNX_FIB_ENTRY_H_
+#define	_CCNX_FIB_ENTRY_H_
+
+#include "ns3/ptr.h"
+#include "ns3/nstime.h"
+#include "ns3/ccnx.h"
+#include "ns3/ccnx-face.h"
+
+#include <boost/multi_index_container.hpp>
+#include <boost/multi_index/tag.hpp>
+#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/composite_key.hpp>
+#include <boost/multi_index/hashed_index.hpp>
+#include <boost/multi_index/random_access_index.hpp>
+#include <boost/multi_index/member.hpp>
+#include <boost/multi_index/mem_fun.hpp>
+
+namespace ns3
+{
+
+class CcnxNameComponents;
+
+/**
+ * \ingroup ccnx
+ * \brief Structure holding various parameters associated with a (FibEntry, Face) tuple
+ */
+class CcnxFibFaceMetric
+{
+public:
+  /**
+   * @brief Color codes for FIB face status
+   */
+  enum Status { NDN_FIB_GREEN = 1,
+                NDN_FIB_YELLOW = 2,
+                NDN_FIB_RED = 3 };
+public:
+  /**
+   * \brief Metric constructor
+   *
+   * \param face Face for which metric
+   * \param cost Initial value for routing cost
+   */
+  CcnxFibFaceMetric (Ptr<CcnxFace> face, int32_t cost)
+    : m_face (face)
+    , m_status (NDN_FIB_YELLOW)
+    , m_routingCost (cost)
+    , m_sRtt   (Seconds (0))
+    , m_rttVar (Seconds (0))
+  { }
+
+  /**
+   * \brief Comparison operator used by boost::multi_index::identity<>
+   */
+  bool
+  operator< (const CcnxFibFaceMetric &fm) const { return *m_face < *fm.m_face; } // return identity of the face
+
+  /**
+   * @brief Comparison between CcnxFibFaceMetric and CcnxFace
+   */
+  bool
+  operator< (const Ptr<CcnxFace> &face) const { return *m_face < *face; } 
+
+  /**
+   * @brief Return CcnxFace associated with CcnxFibFaceMetric
+   */
+  Ptr<CcnxFace>
+  GetFace () const { return m_face; }
+
+  /**
+   * \brief Recalculate smoothed RTT and RTT variation
+   * \param rttSample RTT sample
+   */
+  void
+  UpdateRtt (const Time &rttSample);
+  
+private:
+  friend std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric);
+public:
+  Ptr<CcnxFace> m_face; ///< Face
+  
+  Status m_status;		///< \brief Status of the next hop: 
+				///<		- NDN_FIB_GREEN
+				///<		- NDN_FIB_YELLOW
+				///<		- NDN_FIB_RED
+  
+  int32_t m_routingCost; ///< \brief routing protocol cost (interpretation of the value depends on the underlying routing protocol)
+
+  Time m_sRtt;         ///< \brief smoothed round-trip time
+  Time m_rttVar;       ///< \brief round-trip time variation
+};
+
+/**
+ * \ingroup ccnx
+ * \brief Typedef for indexed face container of CcnxFibEntry
+ *
+ * Currently, there are 2 indexes:
+ * - by face (used to find record and update metric)
+ * - by metric (face ranking)
+ * - random access index (for fast lookup on nth face). Order is
+ *   maintained manually to be equal to the 'by metric' order
+ */
+struct CcnxFibFaceMetricContainer
+{
+  /// @cond include_hidden
+  typedef boost::multi_index::multi_index_container<
+    CcnxFibFaceMetric,
+    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<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::i_metric>,
+        boost::multi_index::composite_key<
+          CcnxFibFaceMetric,
+          boost::multi_index::member<CcnxFibFaceMetric,CcnxFibFaceMetric::Status,&CcnxFibFaceMetric::m_status>,
+          boost::multi_index::member<CcnxFibFaceMetric,int32_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::i_nth>
+      >
+    >
+   > type;
+  /// @endcond
+};
+
+/**
+ * \ingroup ccnx
+ * \brief Structure for FIB table entry, holding indexed list of
+ *        available faces and their respective metrics
+ */
+class CcnxFibEntry : public SimpleRefCount<CcnxFibEntry>
+{
+public:
+  class NoFaces {}; ///< @brief Exception class for the case when FIB entry is not found
+  
+  /**
+   * \brief Constructor
+   * \param prefix smart pointer to the prefix for the FIB entry
+   */
+  CcnxFibEntry (const Ptr<const CcnxNameComponents> &prefix)
+  : m_prefix (prefix)
+  , m_needsProbing (false)
+  { }
+  
+  /**
+   * \brief Update status of FIB next hop
+   * \param status Status to set on the FIB entry
+   */
+  void UpdateStatus (Ptr<CcnxFace> face, CcnxFibFaceMetric::Status status);
+
+  /**
+   * \brief Add or update routing metric of FIB next hop
+   *
+   * Initial status of the next hop is set to YELLOW
+   */
+  void AddOrUpdateRoutingMetric (Ptr<CcnxFace> face, int32_t metric);
+
+  /**
+   * @brief Invalidate face
+   *
+   * Set routing metric on all faces to max and status to RED
+   */
+  void
+  Invalidate ();
+
+  /**
+   * @brief Update RTT averages for the face
+   */
+  void
+  UpdateFaceRtt (Ptr<CcnxFace> face, const Time &sample);
+  
+  /**
+   * \brief Get prefix for the FIB entry
+   */
+  const CcnxNameComponents&
+  GetPrefix () const { return *m_prefix; }
+
+  /**
+   * \brief Find "best route" candidate, skipping `skip' first candidates (modulo # of faces)
+   *
+   * throws CcnxFibEntry::NoFaces if m_faces.size()==0
+   */
+  const CcnxFibFaceMetric &
+  FindBestCandidate (uint32_t skip = 0) const;
+
+  /**
+   * @brief Remove record associated with `face`
+   */
+  void
+  RemoveFace (const Ptr<CcnxFace> &face)
+  {
+    m_faces.erase (face);
+  }
+	
+private:
+  friend std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry);
+
+public:
+  Ptr<const CcnxNameComponents> m_prefix; ///< \brief Prefix of the FIB entry
+  CcnxFibFaceMetricContainer::type m_faces; ///< \brief Indexed list of faces
+
+  bool m_needsProbing;      ///< \brief flag indicating that probing should be performed 
+};
+
+std::ostream& operator<< (std::ostream& os, const CcnxFibEntry &entry);
+std::ostream& operator<< (std::ostream& os, const CcnxFibFaceMetric &metric);
+
+} // ns3
+
+#endif // _CCNX_FIB_ENTRY_H_
diff --git a/model/fib/ccnx-fib-impl.cc b/model/fib/ccnx-fib-impl.cc
new file mode 100644
index 0000000..107f072
--- /dev/null
+++ b/model/fib/ccnx-fib-impl.cc
@@ -0,0 +1,252 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnx-fib-impl.h"
+
+#include "ns3/ccnx.h"
+#include "ns3/ccnx-face.h"
+#include "ns3/ccnx-interest-header.h"
+
+#include "ns3/node.h"
+#include "ns3/assert.h"
+#include "ns3/names.h"
+#include "ns3/log.h"
+
+#include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
+
+NS_LOG_COMPONENT_DEFINE ("CcnxFibImpl");
+
+namespace ns3 {
+
+NS_OBJECT_ENSURE_REGISTERED (CcnxFibImpl);
+
+TypeId 
+CcnxFibImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::CcnxFib") // cheating ns3 object system
+    .SetParent<CcnxFib> ()
+    .SetGroupName ("Ccnx")
+    .AddConstructor<CcnxFibImpl> ()
+  ;
+  return tid;
+}
+
+CcnxFibImpl::CcnxFibImpl ()
+{
+}
+
+void
+CcnxFibImpl::NotifyNewAggregate ()
+{
+  Object::NotifyNewAggregate ();
+}
+
+void 
+CcnxFibImpl::DoDispose (void)
+{
+  clear ();
+  Object::DoDispose ();
+}
+
+
+Ptr<CcnxFibEntry>
+CcnxFibImpl::LongestPrefixMatch (const CcnxInterestHeader &interest)
+{
+  super::iterator item = super::longest_prefix_match (interest.GetName ());
+  // @todo use predicate to search with exclude filters
+
+  if (item == super::end ())
+    return 0;
+  else
+    return item->payload ();
+}
+
+
+Ptr<CcnxFibEntry>
+CcnxFibImpl::Add (const CcnxNameComponents &prefix, Ptr<CcnxFace> face, int32_t metric)
+{
+  return Add (Create<CcnxNameComponents> (prefix), face, metric);
+}
+  
+Ptr<CcnxFibEntry>
+CcnxFibImpl::Add (const Ptr<const CcnxNameComponents> &prefix, Ptr<CcnxFace> face, int32_t metric)
+{
+  NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix) << boost::cref(*face) << metric);
+
+  // will add entry if doesn't exists, or just return an iterator to the existing entry
+  std::pair< super::iterator, bool > result = super::insert (*prefix, 0);
+  if (result.first != super::end ())
+    {
+      if (result.second)
+        {
+            Ptr<CcnxFibEntryImpl> newEntry = Create<CcnxFibEntryImpl> (prefix);
+            newEntry->SetTrie (result.first);
+            result.first->set_payload (newEntry);
+        }
+  
+      super::modify (result.first,
+                     ll::bind (&CcnxFibEntry::AddOrUpdateRoutingMetric, ll::_1, face, metric));
+    
+      return result.first->payload ();
+    }
+  else
+    return 0;
+}
+
+void
+CcnxFibImpl::Remove (const Ptr<const CcnxNameComponents> &prefix)
+{
+  NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix));
+
+  super::erase (*prefix);
+}
+
+// void
+// CcnxFibImpl::Invalidate (const Ptr<const CcnxNameComponents> &prefix)
+// {
+//   NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId () << boost::cref(*prefix));
+
+//   super::iterator foundItem, lastItem;
+//   bool reachLast;
+//   boost::tie (foundItem, reachLast, lastItem) = super::getTrie ().find (*prefix);
+  
+//   if (!reachLast || lastItem->payload () == 0)
+//     return; // nothing to invalidate
+
+//   super::modify (lastItem,
+//                  ll::bind (&CcnxFibEntry::Invalidate, ll::_1));
+// }
+
+void
+CcnxFibImpl::InvalidateAll ()
+{
+  NS_LOG_FUNCTION (this->GetObject<Node> ()->GetId ());
+
+  super::parent_trie::recursive_iterator item (super::getTrie ());
+  super::parent_trie::recursive_iterator end (0);
+  for (; item != end; item++)
+    {
+      if (item->payload () == 0) continue;
+
+      super::modify (&(*item),
+                     ll::bind (&CcnxFibEntry::Invalidate, ll::_1));
+    }
+}
+
+void
+CcnxFibImpl::Remove (super::parent_trie &item, Ptr<CcnxFace> face)
+{
+  if (item.payload () == 0) return;
+  NS_LOG_FUNCTION (this);
+
+  super::modify (&item,
+                 ll::bind (&CcnxFibEntry::RemoveFace, ll::_1, face));
+}
+
+void
+CcnxFibImpl::RemoveFromAll (Ptr<CcnxFace> face)
+{
+  NS_LOG_FUNCTION (this);
+
+  std::for_each (super::parent_trie::recursive_iterator (super::getTrie ()),
+                 super::parent_trie::recursive_iterator (0), 
+                 ll::bind (static_cast< void (CcnxFib::*) (super::parent_trie &, Ptr<CcnxFace>) > (&CcnxFibImpl::Remove),
+                           this, ll::_1, face));
+
+  super::parent_trie::recursive_iterator trieNode (super::getTrie ());
+  super::parent_trie::recursive_iterator end (0);
+  for (; trieNode != end; trieNode++)
+    {
+      if (trieNode->payload () == 0) continue;
+      
+      if (trieNode->payload ()->m_faces.size () == 0)
+        {
+          trieNode = super::parent_trie::recursive_iterator (trieNode->erase ());
+        }
+    }
+}
+
+void
+CcnxFibImpl::Print (std::ostream &os) const
+{
+  // !!! unordered_set imposes "random" order of item in the same level !!!
+  super::parent_trie::const_recursive_iterator item (super::getTrie ());
+  super::parent_trie::const_recursive_iterator end (0);
+  for (; item != end; item++)
+    {
+      if (item->payload () == 0) continue;
+
+      os << item->payload ()->GetPrefix () << "\t" << *item->payload () << "\n";
+    }
+}
+
+uint32_t
+CcnxFibImpl::GetSize () const
+{
+  return super::getPolicy ().size ();
+}
+
+Ptr<const CcnxFibEntry>
+CcnxFibImpl::Begin ()
+{
+  super::parent_trie::const_recursive_iterator item (super::getTrie ());
+  super::parent_trie::const_recursive_iterator end (0);
+  for (; item != end; item++)
+    {
+      if (item->payload () == 0) continue;
+      break;
+    }
+
+  if (item == end)
+    return End ();
+  else
+    return item->payload ();
+}
+
+Ptr<const CcnxFibEntry>
+CcnxFibImpl::End ()
+{
+  return 0;
+}
+
+Ptr<const CcnxFibEntry>
+CcnxFibImpl::Next (Ptr<const CcnxFibEntry> from)
+{
+  if (from == 0) return 0;
+  
+  super::parent_trie::const_recursive_iterator item (*StaticCast<const CcnxFibEntryImpl> (from)->to_iterator ());
+  super::parent_trie::const_recursive_iterator end (0);
+  for (item++; item != end; item++)
+    {
+      if (item->payload () == 0) continue;
+      break;
+    }
+
+  if (item == end)
+    return End ();
+  else
+    return item->payload ();
+}
+
+
+} // namespace ns3
diff --git a/model/fib/ccnx-fib-impl.h b/model/fib/ccnx-fib-impl.h
new file mode 100644
index 0000000..d85dcfd
--- /dev/null
+++ b/model/fib/ccnx-fib-impl.h
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef _CCNX_FIB_IMPL_H_
+#define	_CCNX_FIB_IMPL_H_
+
+#include "ns3/ccnx-fib.h"
+#include "ns3/ccnx-name-components.h"
+
+#include "../../utils/trie-with-policy.h"
+#include "../../utils/counting-policy.h"
+
+namespace ns3 {
+
+class CcnxFibEntryImpl : public CcnxFibEntry
+{
+public:
+  typedef ndnSIM::trie_with_policy<
+    CcnxNameComponents,
+    ndnSIM::smart_pointer_payload_traits<CcnxFibEntryImpl>,
+    ndnSIM::counting_policy_traits
+    > trie;
+
+  CcnxFibEntryImpl (const Ptr<const CcnxNameComponents> &prefix)
+    : CcnxFibEntry (prefix)
+    , item_ (0)
+  {
+  }
+
+  void
+  SetTrie (trie::iterator item)
+  {
+    item_ = item;
+  }
+
+  trie::iterator to_iterator () { return item_; }
+  trie::const_iterator to_iterator () const { return item_; }
+  
+private:
+  trie::iterator item_;
+};
+
+struct CcnxFibEntryContainer
+{
+  typedef ndnSIM::trie_with_policy<
+    CcnxNameComponents,
+    ndnSIM::smart_pointer_payload_traits<CcnxFibEntryImpl>,
+    ndnSIM::counting_policy_traits
+    > type;
+};
+
+/**
+ * \ingroup ccnx
+ * \brief Class implementing FIB functionality
+ */
+class CcnxFibImpl : public CcnxFib,
+                    private CcnxFibEntryContainer::type
+{
+public:
+  typedef CcnxFibEntryContainer::type super;
+  
+  /**
+   * \brief Interface ID
+   *
+   * \return interface ID
+   */
+  static TypeId GetTypeId ();
+
+  /**
+   * \brief Constructor
+   */
+  CcnxFibImpl ();
+
+  virtual Ptr<CcnxFibEntry>
+  LongestPrefixMatch (const CcnxInterestHeader &interest);
+  
+  virtual Ptr<CcnxFibEntry>
+  Add (const CcnxNameComponents &prefix, Ptr<CcnxFace> face, int32_t metric);
+
+  virtual Ptr<CcnxFibEntry>
+  Add (const Ptr<const CcnxNameComponents> &prefix, Ptr<CcnxFace> face, int32_t metric);
+
+  virtual void
+  Remove (const Ptr<const CcnxNameComponents> &prefix);
+
+  virtual void
+  InvalidateAll ();
+  
+  virtual void
+  RemoveFromAll (Ptr<CcnxFace> face);
+
+  virtual void
+  Print (std::ostream &os) const;
+
+  virtual uint32_t
+  GetSize () const;
+
+  virtual Ptr<const CcnxFibEntry>
+  Begin ();
+
+  virtual Ptr<const CcnxFibEntry>
+  End ();
+
+  virtual Ptr<const CcnxFibEntry>
+  Next (Ptr<const CcnxFibEntry> item);
+  
+  // /**
+  //  * @brief Modify element in container
+  //  */
+  // template<typename Modifier>
+  // bool
+  // modify (Ptr<CcnxFibEntry> item, Modifier mod)
+  // {
+  //   return super::modify (StaticCast<CcnxFibEntryImpl> (item)->to_iterator (), mod);
+  // }
+  
+protected:
+  // inherited from Object class
+  virtual void NotifyNewAggregate (); ///< @brief Notify when object is aggregated
+  virtual void DoDispose (); ///< @brief Perform cleanup
+
+private:
+  /**
+   * @brief Remove reference to a face from the entry. If entry had only this face, the whole
+   * entry will be removed
+   */
+  void
+  Remove (super::parent_trie &item, Ptr<CcnxFace> face);
+  
+private:
+  Ptr<Node> m_node;
+};
+ 
+} // namespace ns3
+
+#endif	/* _CCNX_FIB_IMPL_H_ */
diff --git a/model/fib/ccnx-fib.cc b/model/fib/ccnx-fib.cc
new file mode 100644
index 0000000..fdd1aea
--- /dev/null
+++ b/model/fib/ccnx-fib.cc
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ccnx-fib.h"
+
+#include "ccnx-fib-impl.h"
+
+#include "ns3/ccnx.h"
+#include "ns3/ccnx-face.h"
+#include "ns3/ccnx-interest-header.h"
+#include "ns3/ccnx-name-components.h"
+
+#include "ns3/node.h"
+#include "ns3/names.h"
+
+#include <boost/ref.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+namespace ll = boost::lambda;
+
+namespace ns3 {
+
+using namespace __ccnx_private;
+
+TypeId 
+CcnxFib::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::private::CcnxFib") // cheating ns3 object system
+    .SetParent<Object> ()
+    .SetGroupName ("Ccnx")
+  ;
+  return tid;
+}
+
+std::ostream& operator<< (std::ostream& os, const CcnxFib &fib)
+{
+  os << "Node " << Names::FindName (fib.GetObject<Node>()) << "\n";
+  os << "  Dest prefix      Interfaces(Costs)                  \n";
+  os << "+-------------+--------------------------------------+\n";
+
+  fib.Print (os);
+  return os;
+}
+
+} // namespace ns3
diff --git a/model/fib/ccnx-fib.h b/model/fib/ccnx-fib.h
new file mode 100644
index 0000000..eae0c65
--- /dev/null
+++ b/model/fib/ccnx-fib.h
@@ -0,0 +1,189 @@
+/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
+/*
+ * Copyright (c) 2011 University of California, Los Angeles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef _CCNX_FIB_H_
+#define	_CCNX_FIB_H_
+
+#include "ns3/simple-ref-count.h"
+#include "ns3/node.h"
+
+#include "ns3/ccnx-fib-entry.h"
+
+namespace ns3 {
+
+class CcnxInterestHeader;
+
+/**
+ * \ingroup ccnx
+ * \brief Class implementing FIB functionality
+ */
+class CcnxFib : public Object
+{
+public:
+  /**
+   * \brief Interface ID
+   *
+   * \return interface ID
+   */
+  static TypeId GetTypeId ();
+  /**
+   * @brief Default constructor
+   */
+  CcnxFib () {}
+  
+  /**
+   * @brief Virtual destructor
+   */
+  virtual ~CcnxFib () { };
+  
+  /**
+   * \brief Perform longest prefix match
+   *
+   * \todo Implement exclude filters
+   *
+   * \param interest Interest packet header
+   * \returns If entry found a valid iterator will be returned, otherwise end ()
+   */
+  virtual Ptr<CcnxFibEntry>
+  LongestPrefixMatch (const CcnxInterestHeader &interest) = 0;
+  
+  /**
+   * \brief Add or update FIB entry
+   *
+   * If the entry exists, metric will be updated. Otherwise, new entry will be created
+   *
+   * Entries in FIB never deleted. They can be invalidated with metric==NETWORK_UNREACHABLE
+   *
+   * @param name	Prefix
+   * @param face	Forwarding face
+   * @param metric	Routing metric
+   */
+  virtual Ptr<CcnxFibEntry>
+  Add (const CcnxNameComponents &prefix, Ptr<CcnxFace> face, int32_t metric) = 0;
+
+  /**
+   * \brief Add or update FIB entry using smart pointer to prefix
+   *
+   * If the entry exists, metric will be updated. Otherwise, new entry will be created
+   *
+   * Entries in FIB never deleted. They can be invalidated with metric==NETWORK_UNREACHABLE
+   *
+   * @param name	Smart pointer to prefix
+   * @param face	Forwarding face
+   * @param metric	Routing metric
+   */
+  virtual Ptr<CcnxFibEntry>
+  Add (const Ptr<const CcnxNameComponents> &prefix, Ptr<CcnxFace> face, int32_t metric) = 0;
+
+  /**
+   * @brief Remove FIB entry
+   *
+   * ! ATTENTION ! Use with caution.  All PIT entries referencing the corresponding FIB entry will become invalid.
+   * So, simulation may crash.
+   *
+   * @param name	Smart pointer to prefix
+   */
+  virtual void
+  Remove (const Ptr<const CcnxNameComponents> &prefix) = 0;
+
+  // /**
+  //  * @brief Invalidate FIB entry ("Safe" version of Remove)
+  //  *
+  //  * All faces for the entry will be assigned maximum routing metric and NDN_FIB_RED status   
+  //  * @param name	Smart pointer to prefix
+  //  */
+  // virtual void
+  // Invalidate (const Ptr<const CcnxNameComponents> &prefix) = 0;
+
+  /**
+   * @brief Invalidate all FIB entries
+   */
+  virtual void
+  InvalidateAll () = 0;
+  
+  /**
+   * @brief Remove all references to a face from FIB.  If for some enty that face was the only element,
+   * this FIB entry will be removed.
+   */
+  virtual void
+  RemoveFromAll (Ptr<CcnxFace> face) = 0;
+
+  /**
+   * @brief Print out entries in FIB
+   */
+  virtual void
+  Print (std::ostream &os) const = 0;
+
+  /**
+   * @brief Get number of entries in FIB
+   */
+  virtual uint32_t
+  GetSize () const = 0;
+
+  /**
+   * @brief Return first element of FIB (no order guaranteed)
+   */
+  virtual Ptr<const CcnxFibEntry>
+  Begin () = 0;
+
+  /**
+   * @brief Return item next after last (no order guaranteed)
+   */
+  virtual Ptr<const CcnxFibEntry>
+  End () = 0;
+
+  /**
+   * @brief Advance the iterator
+   */
+  virtual Ptr<const CcnxFibEntry>
+  Next (Ptr<const CcnxFibEntry>) = 0;
+
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+  
+  /**
+   * @brief Static call to cheat python bindings
+   */
+  static inline Ptr<CcnxFib>
+  GetCcnxFib (Ptr<Object> node);
+
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////////////
+  
+private:
+  CcnxFib(const CcnxFib&) {} ; ///< \brief copy constructor is disabled
+};
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+std::ostream& operator<< (std::ostream& os, const CcnxFib &fib);
+
+Ptr<CcnxFib>
+CcnxFib::GetCcnxFib (Ptr<Object> node)
+{
+  return node->GetObject<CcnxFib> ();
+}
+
+} // namespace ns3
+
+#endif // _CCNX_FIB_H_