publisher: implement routing table dataset publisher

refs: #3631, #3634

Change-Id: I7e961fdd0857690bee65d2bdfa4cf3de90ccac06
diff --git a/docs/manpages/nlsrc.rst b/docs/manpages/nlsrc.rst
index 413002a..83d7795 100644
--- a/docs/manpages/nlsrc.rst
+++ b/docs/manpages/nlsrc.rst
@@ -26,9 +26,15 @@
 
 ``COMMAND``
 
-  ``status``
+  ``lsdb``
     Retrieve LSDB status information
 
+  ``routing``
+    Retrieve routing table status information
+
+  ``status``
+    Retrieve LSDB status and routing table status information
+
   ``advertise``
     Add a Name prefix to be advertised by NLSR
 
diff --git a/src/nlsr.cpp b/src/nlsr.cpp
index c31df2f..ab4a073 100644
--- a/src/nlsr.cpp
+++ b/src/nlsr.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -55,22 +55,21 @@
   , m_routingTable(scheduler)
   , m_fib(m_nlsrFace, scheduler, m_adjacencyList, m_confParam, m_keyChain)
   , m_namePrefixTable(*this, m_routingTable.afterRoutingChange)
-  , m_localhostDispatcher(m_nlsrFace, m_keyChain)
-  , m_routerNameDispatcher(m_nlsrFace, m_keyChain)
-  , m_lsdbDatasetHandler(m_nlsrLsdb,
-                         m_localhostDispatcher,
-                         m_routerNameDispatcher,
-                         m_nlsrFace,
-                         m_keyChain)
+  , m_dispatcher(m_nlsrFace, m_keyChain)
+  , m_datasetHandler(m_nlsrLsdb,
+                     m_routingTable,
+                     m_dispatcher,
+                     m_nlsrFace,
+                     m_keyChain)
   , m_helloProtocol(*this, scheduler)
   , m_validator(ndn::make_unique<ndn::security::v2::CertificateFetcherDirectFetch>(m_nlsrFace))
   , m_controller(m_nlsrFace, m_keyChain)
   , m_faceDatasetController(m_nlsrFace, m_keyChain)
-  , m_prefixUpdateProcessor(m_localhostDispatcher,
+  , m_prefixUpdateProcessor(m_dispatcher,
                             m_nlsrFace,
                             m_namePrefixList,
                             m_nlsrLsdb)
-  , m_nfdRibCommandProcessor(m_localhostDispatcher,
+  , m_nfdRibCommandProcessor(m_dispatcher,
                              m_namePrefixList,
                              m_nlsrLsdb)
   , m_statsCollector(m_nlsrLsdb, m_helloProtocol)
@@ -133,12 +132,7 @@
 Nlsr::addDispatcherTopPrefix(const ndn::Name& topPrefix)
 {
   try {
-    if (topPrefix.equals(m_confParam.getRouterPrefix())) {
-      m_routerNameDispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
-    }
-    else {
-      m_localhostDispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
-    }
+    m_dispatcher.addTopPrefix(topPrefix, false, m_signingInfo);
   }
   catch (const std::exception& e) {
     NLSR_LOG_ERROR("Error setting top-level prefix in dispatcher: " << e.what() << "\n");
@@ -234,7 +228,7 @@
 {
   NLSR_LOG_DEBUG("Initializing Nlsr");
   m_confParam.buildRouterPrefix();
-  m_lsdbDatasetHandler.setRouterNameCommandPrefix(m_confParam.getRouterPrefix());
+  m_datasetHandler.setRouterNameCommandPrefix(m_confParam.getRouterPrefix());
   m_nlsrLsdb.setLsaRefreshTime(ndn::time::seconds(m_confParam.getLsaRefreshTime()));
   m_nlsrLsdb.setThisRouterPrefix(m_confParam.getRouterPrefix().toUri());
   m_fib.setEntryRefreshTime(2 * m_confParam.getLsaRefreshTime());
diff --git a/src/nlsr.hpp b/src/nlsr.hpp
index f16e918..10999d2 100644
--- a/src/nlsr.hpp
+++ b/src/nlsr.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -29,7 +29,7 @@
 #include "lsdb.hpp"
 #include "name-prefix-list.hpp"
 #include "test-access-control.hpp"
-#include "publisher/lsdb-dataset-interest-handler.hpp"
+#include "publisher/dataset-interest-handler.hpp"
 #include "route/fib.hpp"
 #include "route/name-prefix-table.hpp"
 #include "route/routing-table.hpp"
@@ -231,10 +231,10 @@
     m_isRouteCalculationScheduled = ircs;
   }
 
-  LsdbDatasetInterestHandler&
-  getLsdbDatasetHandler()
+  DatasetInterestHandler&
+  getDatasetHandler()
   {
-    return m_lsdbDatasetHandler;
+    return m_datasetHandler;
   }
 
   void
@@ -356,15 +356,9 @@
   }
 
   ndn::mgmt::Dispatcher&
-  getLocalhostDispatcher()
+  getDispatcher()
   {
-    return m_localhostDispatcher;
-  }
-
-  ndn::mgmt::Dispatcher&
-  getRouterNameDispatcher()
-  {
-    return m_routerNameDispatcher;
+    return m_dispatcher;
   }
 
   void
@@ -496,10 +490,9 @@
   Fib m_fib;
   NamePrefixTable m_namePrefixTable;
 
-  ndn::mgmt::Dispatcher m_localhostDispatcher;
-  ndn::mgmt::Dispatcher m_routerNameDispatcher;
+  ndn::mgmt::Dispatcher m_dispatcher;
 
-  LsdbDatasetInterestHandler m_lsdbDatasetHandler;
+  DatasetInterestHandler m_datasetHandler;
 
 PUBLIC_WITH_TESTS_ELSE_PRIVATE:
   HelloProtocol m_helloProtocol;
diff --git a/src/publisher/lsdb-dataset-interest-handler.cpp b/src/publisher/dataset-interest-handler.cpp
similarity index 66%
rename from src/publisher/lsdb-dataset-interest-handler.cpp
rename to src/publisher/dataset-interest-handler.cpp
index 53cdfbc..efd76f8 100644
--- a/src/publisher/lsdb-dataset-interest-handler.cpp
+++ b/src/publisher/dataset-interest-handler.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -19,66 +19,56 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
-/*! \file lsdb-dataset-interest-handler.cpp
-
-  This file details a class that is used by NLSRC and other command-line
-  tools to examine the state of NLSR. This system is not designed to
-  be used by routers to publish data to each other.
- */
-
-#include "lsdb-dataset-interest-handler.hpp"
-
+#include "dataset-interest-handler.hpp"
 #include "nlsr.hpp"
 #include "tlv/lsdb-status.hpp"
 #include "logger.hpp"
 
-#include <ndn-cxx/face.hpp>
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 #include <ndn-cxx/util/regex.hpp>
 
 namespace nlsr {
 
-INIT_LOGGER("LsdbDatasetInterestHandler");
+INIT_LOGGER("DatasetInterestHandler");
 
 const ndn::PartialName ADJACENCIES_DATASET = ndn::PartialName("lsdb/adjacencies");
 const ndn::PartialName COORDINATES_DATASET = ndn::PartialName("lsdb/coordinates");
 const ndn::PartialName NAMES_DATASET = ndn::PartialName("lsdb/names");
-const ndn::PartialName LISTS_DATASET = ndn::PartialName("lsdb/list");
+const ndn::PartialName RT_DATASET = ndn::PartialName("routing-table");
 
-LsdbDatasetInterestHandler::LsdbDatasetInterestHandler(Lsdb& lsdb,
-                                                       ndn::mgmt::Dispatcher& localHostDispatcher,
-                                                       ndn::mgmt::Dispatcher& routerNameDispatcher,
-                                                       ndn::Face& face,
-                                                       ndn::KeyChain& keyChain)
+DatasetInterestHandler::DatasetInterestHandler(const Lsdb& lsdb,
+                                               const RoutingTable& rt,
+                                               ndn::mgmt::Dispatcher& dispatcher,
+                                               const ndn::Face& face,
+                                               const ndn::KeyChain& keyChain)
   : m_lsdb(lsdb)
-  , m_localhostDispatcher(localHostDispatcher)
-  , m_routerNameDispatcher(routerNameDispatcher)
+  , m_dispatcher(dispatcher)
+  , m_routingTableEntries(rt.getRoutingTableEntry())
+  , m_dryRoutingTableEntries(rt.getDryRoutingTableEntry())
 {
-  NLSR_LOG_DEBUG("Setting dispatcher for lsdb status dataset:");
-  setDispatcher(m_localhostDispatcher);
-  setDispatcher(m_routerNameDispatcher);
+  setDispatcher(m_dispatcher);
 }
 
 void
-LsdbDatasetInterestHandler::setDispatcher(ndn::mgmt::Dispatcher& dispatcher)
+DatasetInterestHandler::setDispatcher(ndn::mgmt::Dispatcher& dispatcher)
 {
   dispatcher.addStatusDataset(ADJACENCIES_DATASET,
     ndn::mgmt::makeAcceptAllAuthorization(),
-    std::bind(&LsdbDatasetInterestHandler::publishAdjStatus, this, _1, _2, _3));
+    std::bind(&DatasetInterestHandler::publishAdjStatus, this, _1, _2, _3));
   dispatcher.addStatusDataset(COORDINATES_DATASET,
     ndn::mgmt::makeAcceptAllAuthorization(),
-    std::bind(&LsdbDatasetInterestHandler::publishCoordinateStatus, this, _1, _2, _3));
+    std::bind(&DatasetInterestHandler::publishCoordinateStatus, this, _1, _2, _3));
   dispatcher.addStatusDataset(NAMES_DATASET,
     ndn::mgmt::makeAcceptAllAuthorization(),
-    std::bind(&LsdbDatasetInterestHandler::publishNameStatus, this, _1, _2, _3));
-  dispatcher.addStatusDataset(LISTS_DATASET,
+    std::bind(&DatasetInterestHandler::publishNameStatus, this, _1, _2, _3));
+  dispatcher.addStatusDataset(RT_DATASET,
     ndn::mgmt::makeAcceptAllAuthorization(),
-    std::bind(&LsdbDatasetInterestHandler::publishAllStatus, this, _1, _2, _3));
+    std::bind(&DatasetInterestHandler::publishRtStatus, this, _1, _2, _3));
 }
 
 void
-LsdbDatasetInterestHandler::publishAdjStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                                             ndn::mgmt::StatusDatasetContext& context)
+DatasetInterestHandler::publishAdjStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                                         ndn::mgmt::StatusDatasetContext& context)
 {
   NLSR_LOG_DEBUG("Received interest:  " << interest);
 
@@ -104,8 +94,8 @@
 }
 
 void
-LsdbDatasetInterestHandler::publishCoordinateStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                                                    ndn::mgmt::StatusDatasetContext& context)
+DatasetInterestHandler::publishCoordinateStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                                                ndn::mgmt::StatusDatasetContext& context)
 {
   auto lsaRange = std::make_pair<std::list<CoordinateLsa>::const_iterator,
                                  std::list<CoordinateLsa>::const_iterator>(
@@ -127,8 +117,8 @@
 }
 
 void
-LsdbDatasetInterestHandler::publishNameStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                                              ndn::mgmt::StatusDatasetContext& context)
+DatasetInterestHandler::publishNameStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                                          ndn::mgmt::StatusDatasetContext& context)
 {
   auto lsaRange = std::make_pair<std::list<NameLsa>::const_iterator, std::list<NameLsa>::const_iterator>(
     m_lsdb.getNameLsdb().cbegin(), m_lsdb.getNameLsdb().cend());
@@ -150,24 +140,42 @@
 }
 
 void
-LsdbDatasetInterestHandler::publishAllStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                                             ndn::mgmt::StatusDatasetContext& context)
+DatasetInterestHandler::publishRtStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                                        ndn::mgmt::StatusDatasetContext& context)
 {
-  NLSR_LOG_DEBUG("Received interest:  " << interest);
-  tlv::LsdbStatus lsdbStatus;
-  for (const tlv::AdjacencyLsa& tlvLsa : getTlvLsas<tlv::AdjacencyLsa>(m_lsdb)) {
-    lsdbStatus.addAdjacencyLsa(tlvLsa);
+  NLSR_LOG_DEBUG("Received interest for routing table:  " << interest);
+  tlv::RoutingTable tlvRoutingTable;
+
+  for (const auto& rte : m_routingTableEntries) {
+    std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(rte);
+    tlvRoutingTable.setDestination(*tlvDes);
+
+    for (const auto& nh : rte.getNexthopList().getNextHops()) {
+      tlv::NextHop tlvNexthop;
+      tlvNexthop.setUri(nh.getConnectingFaceUri());
+      tlvNexthop.setCost(nh.getRouteCost());
+      tlvRoutingTable.addNexthops(tlvNexthop);
+    }
+
+    const ndn::Block& wire = tlvRoutingTable.wireEncode();
+    context.append(wire);
+  }
+  if (!m_dryRoutingTableEntries.empty()) {
+    for (const auto& dry_rte : m_dryRoutingTableEntries ) {
+        std::shared_ptr<tlv::Destination> tlvDes = tlv::makeDes(dry_rte);
+        tlvRoutingTable.setDestination(*tlvDes);
+
+        for (const auto& nh : dry_rte.getNexthopList().getNextHops()) {
+          tlv::NextHop tlvNexthop;
+          tlvNexthop.setUri(nh.getConnectingFaceUri());
+          tlvNexthop.setCost(nh.getRouteCost());
+          tlvRoutingTable.addNexthops(tlvNexthop);
+        }
+        const ndn::Block& wire = tlvRoutingTable.wireEncode();
+        context.append(wire);
+      }
   }
 
-  for (const tlv::CoordinateLsa& tlvLsa : getTlvLsas<tlv::CoordinateLsa>(m_lsdb)) {
-    lsdbStatus.addCoordinateLsa(tlvLsa);
-  }
-
-  for (const tlv::NameLsa& tlvLsa : getTlvLsas<tlv::NameLsa>(m_lsdb)) {
-    lsdbStatus.addNameLsa(tlvLsa);
-  }
-  const ndn::Block& wire = lsdbStatus.wireEncode();
-  context.append(wire);
   context.end();
 }
 
@@ -250,5 +258,4 @@
 
 }
 
-
 } // namespace nlsr
diff --git a/src/publisher/lsdb-dataset-interest-handler.hpp b/src/publisher/dataset-interest-handler.hpp
similarity index 60%
rename from src/publisher/lsdb-dataset-interest-handler.hpp
rename to src/publisher/dataset-interest-handler.hpp
index e01a5da..00d8c1d 100644
--- a/src/publisher/lsdb-dataset-interest-handler.hpp
+++ b/src/publisher/dataset-interest-handler.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -19,31 +19,47 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
-#ifndef NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
-#define NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
+ /*! \file dataset-interest-handler.hpp
+
+  This file details a class that is used by NLSRC and other command-line
+  tools to examine the state of NLSR. This class doesn't only handle interest
+  from local host, but also handle interests from remote router.
+  This system is not designed to
+  be used by routers to publish data to each other.
+ */
+
+#ifndef NLSR_PUBLISHER_DATASET_INTEREST_HANDLER_HPP
+#define NLSR_PUBLISHER_DATASET_INTEREST_HANDLER_HPP
+
+#include "route/routing-table-entry.hpp"
+#include "route/routing-table.hpp"
+#include "route/nexthop-list.hpp"
+#include "lsdb.hpp"
+#include "logger.hpp"
 
 #include "tlv/adjacency-lsa.hpp"
 #include "tlv/coordinate-lsa.hpp"
 #include "tlv/name-lsa.hpp"
-#include "lsdb.hpp"
+#include "tlv/routing-table-status.hpp"
+#include "tlv/routing-table-entry.hpp"
 
 #include <ndn-cxx/mgmt/dispatcher.hpp>
 #include <ndn-cxx/face.hpp>
 #include <boost/noncopyable.hpp>
 
 namespace nlsr {
-
 namespace dataset {
-  const ndn::Name::Component ADJACENCY_COMPONENT = ndn::Name::Component{"adjacencies"};
-  const ndn::Name::Component NAME_COMPONENT = ndn::Name::Component{"names"};
-  const ndn::Name::Component COORDINATE_COMPONENT = ndn::Name::Component{"coordinates"};
+const ndn::Name::Component ADJACENCY_COMPONENT = ndn::Name::Component{"adjacencies"};
+const ndn::Name::Component NAME_COMPONENT = ndn::Name::Component{"names"};
+const ndn::Name::Component COORDINATE_COMPONENT = ndn::Name::Component{"coordinates"};
 } // namespace dataset
 
 /*!
-   \brief Class to publish all lsa dataset
+   \brief Class to publish all dataset
    \sa https://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+   \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_DataSet
  */
-class LsdbDatasetInterestHandler : boost::noncopyable
+class DatasetInterestHandler : boost::noncopyable
 {
 public:
   class Error : std::runtime_error
@@ -56,11 +72,11 @@
     }
   };
 
-  LsdbDatasetInterestHandler(Lsdb& lsdb,
-                             ndn::mgmt::Dispatcher& localHostDispatcher,
-                             ndn::mgmt::Dispatcher& routerNameDispatcher,
-                             ndn::Face& face,
-                             ndn::KeyChain& keyChain);
+  DatasetInterestHandler(const Lsdb& lsdb,
+                         const RoutingTable& rt,
+                         ndn::mgmt::Dispatcher& dispatcher,
+                         const ndn::Face& face,
+                         const ndn::KeyChain& keyChain);
 
   ndn::Name&
   getRouterNameCommandPrefix()
@@ -75,12 +91,17 @@
   }
 
 private:
-  /*! \brief Capture-point for Interests to verify Interests are
-   * valid, and then process them.
+  /*! \brief set dispatcher for localhost or remote router
    */
   void
   setDispatcher(ndn::mgmt::Dispatcher& dispatcher);
 
+  /*! \brief provide routing-table dataset
+  */
+  void
+  publishRtStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
+                  ndn::mgmt::StatusDatasetContext& context);
+
   /*! \brief provide adjacent status dataset
    */
   void
@@ -99,18 +120,14 @@
   publishNameStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
                     ndn::mgmt::StatusDatasetContext& context);
 
-  /*! \brief provide ladb status dataset
-   */
-  void
-  publishAllStatus(const ndn::Name& topPrefix, const ndn::Interest& interest,
-                   ndn::mgmt::StatusDatasetContext& context);
-
 private:
   const Lsdb& m_lsdb;
   ndn::Name m_routerNamePrefix;
 
-  ndn::mgmt::Dispatcher& m_localhostDispatcher;
-  ndn::mgmt::Dispatcher& m_routerNameDispatcher;
+  ndn::mgmt::Dispatcher& m_dispatcher;
+
+  const std::list<RoutingTableEntry>& m_routingTableEntries;
+  const std::list<RoutingTableEntry>& m_dryRoutingTableEntries;
 };
 
 template<typename T> std::list<T>
@@ -127,4 +144,4 @@
 
 } // namespace nlsr
 
-#endif // NLSR_PUBLISHER_LSDB_DATASET_INTEREST_HANDLER_HPP
+#endif // NLSR_PUBLISHER_DATASET_INTEREST_HANDLER_HPP
diff --git a/src/route/nexthop-list.hpp b/src/route/nexthop-list.hpp
index 9ba0772..577165f 100644
--- a/src/route/nexthop-list.hpp
+++ b/src/route/nexthop-list.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -87,8 +87,8 @@
     m_nexthopList.clear();
   }
 
-  std::set<NextHop, NextHopComparator>&
-  getNextHops()
+  const std::set<NextHop, NextHopComparator>&
+  getNextHops() const
   {
     return m_nexthopList;
   }
diff --git a/src/route/routing-table.hpp b/src/route/routing-table.hpp
index 60da254..cd7b5f5 100644
--- a/src/route/routing-table.hpp
+++ b/src/route/routing-table.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California
  *
  * This file is part of NLSR (Named-data Link State Routing).
@@ -37,29 +37,30 @@
 class Nlsr;
 class NextHop;
 
-class RoutingTable
+class RoutingTable : boost::noncopyable
 {
 public:
+  explicit
   RoutingTable(ndn::Scheduler& scheduler);
 
   /*! \brief Calculates a list of next hops for each router in the network.
-   * \param pnlsr The NLSR object that contains the LSAs needed for adj. info.
+   *  \param nlsr The NLSR object that contains the LSAs needed for adj. info.
    *
-   * Calculates the list of next hops to every other router in the network.
+   *  Calculates the list of next hops to every other router in the network.
    */
   void
-  calculate(Nlsr& pnlsr);
+  calculate(Nlsr& nlsr);
 
   /*! \brief Adds a next hop to a routing table entry.
-   * \param destRouter The destination router whose RTE we want to modify.
-   * \param nh The next hop to add to the RTE.
+   *  \param destRouter The destination router whose RTE we want to modify.
+   *  \param nh The next hop to add to the RTE.
    */
   void
   addNextHop(const ndn::Name& destRouter, NextHop& nh);
 
   /*! \brief Adds a next hop to a routing table entry in a dry run scenario.
-   * \param destRouter The destination router whose RTE we want to modify.
-   * \param nh The next hop to add to the router.
+   *  \param destRouter The destination router whose RTE we want to modify.
+   *  \param nh The next hop to add to the router.
    */
   void
   addNextHopToDryTable(const ndn::Name& destRouter, NextHop& nh);
@@ -68,8 +69,8 @@
   findRoutingTableEntry(const ndn::Name& destRouter);
 
   /*! \brief Schedules a calculation event in the event scheduler only
-   * if one isn't already scheduled.
-   * \param pnlsr The NLSR whose scheduling status is needed.
+   *  if one isn't already scheduled.
+   *  \param pnlsr The NLSR whose scheduling status is needed.
    */
   void
   scheduleRoutingTableCalculation(Nlsr& pnlsr);
@@ -92,6 +93,24 @@
     return m_routingCalcInterval;
   }
 
+  const std::list<RoutingTableEntry>&
+  getRoutingTableEntry() const
+  {
+    return m_rTable;
+  }
+
+  const std::list<RoutingTableEntry>&
+  getDryRoutingTableEntry() const
+  {
+    return m_dryTable;
+  }
+
+  uint64_t
+  getRtSize()
+  {
+    return m_rTable.size();
+  }
+
 private:
   /*! \brief Calculates a link-state routing table. */
   void
diff --git a/src/tlv/destination.cpp b/src/tlv/destination.cpp
new file mode 100644
index 0000000..6f9f918
--- /dev/null
+++ b/src/tlv/destination.cpp
@@ -0,0 +1,128 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "destination.hpp"
+#include "tlv-nlsr.hpp"
+
+#include <ndn-cxx/util/concepts.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+namespace nlsr {
+namespace tlv {
+
+BOOST_CONCEPT_ASSERT((ndn::WireEncodable<Destination>));
+BOOST_CONCEPT_ASSERT((ndn::WireDecodable<Destination>));
+static_assert(std::is_base_of<ndn::tlv::Error, Destination::Error>::value,
+              "Destination::Error must inherit from tlv::Error");
+
+Destination::Destination() = default;
+
+Destination::Destination(const ndn::Block& block)
+{
+  wireDecode(block);
+}
+
+template<ndn::encoding::Tag TAG>
+size_t
+Destination::wireEncode(ndn::EncodingImpl<TAG>& encoder) const
+{
+  size_t totalLength = 0;
+
+  totalLength += m_name.wireEncode(encoder);
+
+  totalLength += encoder.prependVarNumber(totalLength);
+  totalLength += encoder.prependVarNumber(ndn::tlv::nlsr::Destination);
+
+  return totalLength;
+}
+
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(Destination);
+
+template size_t
+Destination::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
+
+template size_t
+Destination::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+
+const ndn::Block&
+Destination::wireEncode() const
+{
+  if (m_wire.hasWire()) {
+    return m_wire;
+  }
+
+  ndn::EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  ndn::EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+
+  return m_wire;
+}
+
+void
+Destination::wireDecode(const ndn::Block& wire)
+{
+  m_name.clear();
+
+  m_wire = wire;
+
+  if (m_wire.type() != ndn::tlv::nlsr::Destination) {
+    std::stringstream error;
+    error << "Expected Destination Block, but Block is of a different type: #"
+          << m_wire.type();
+    BOOST_THROW_EXCEPTION(Error(error.str()));
+  }
+
+  m_wire.parse();
+
+  ndn::Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == ndn::tlv::Name) {
+    m_name.wireDecode(*val);
+    ++val;
+  }
+  else {
+    BOOST_THROW_EXCEPTION(Error("Missing required Name field"));
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const Destination& Destination)
+{
+  os << "Destination: " << Destination.getName();
+  return os;
+}
+
+std::shared_ptr<Destination>
+makeDes(const RoutingTableEntry& rte)
+{
+  std::shared_ptr<Destination> desInfo = std::make_shared<Destination>();
+
+  desInfo->setName(rte.getDestination());
+
+  return desInfo;
+}
+
+} // namespace tlv
+} // namespace nlsr
diff --git a/src/tlv/destination.hpp b/src/tlv/destination.hpp
new file mode 100644
index 0000000..7c577e8
--- /dev/null
+++ b/src/tlv/destination.hpp
@@ -0,0 +1,103 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_TLV_DESTINATION_HPP
+#define NLSR_TLV_DESTINATION_HPP
+
+#include "route/routing-table-entry.hpp"
+
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/name.hpp>
+#include <boost/throw_exception.hpp>
+
+#include <list>
+
+namespace nlsr {
+namespace tlv {
+
+/*! \brief Data abstraction for Destination
+ *
+ *    Destination := DESTINATION-TYPE TLV-LENGTH
+ *                     Name
+ *
+ * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_DataSet
+ */
+class Destination
+{
+public:
+  class Error : public ndn::tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : ndn::tlv::Error(what)
+    {
+    }
+  };
+
+  Destination();
+
+  explicit
+  Destination(const ndn::Block& block);
+
+  const ndn::Name&
+  getName() const
+  {
+    return m_name;
+  }
+
+  Destination&
+  setName(const ndn::Name& name)
+  {
+    m_name = name;
+    m_wire.reset();
+    return *this;
+  }
+
+  template<ndn::encoding::Tag TAG>
+  size_t
+  wireEncode(ndn::EncodingImpl<TAG>& block) const;
+
+  const ndn::Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const ndn::Block& wire);
+
+private:
+  ndn::Name m_name;
+
+  mutable ndn::Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const Destination& destination);
+
+std::shared_ptr<Destination>
+makeDes(const RoutingTableEntry& rte);
+
+} // namespace tlv
+} // namespace nlsr
+
+#endif // NLSR_TLV_DESTINATION_HPP
diff --git a/src/tlv/lsdb-status.cpp b/src/tlv/lsdb-status.cpp
index 90a711e..e447863 100644
--- a/src/tlv/lsdb-status.cpp
+++ b/src/tlv/lsdb-status.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -26,7 +26,7 @@
 #include <ndn-cxx/encoding/block-helpers.hpp>
 
 namespace nlsr {
-namespace tlv  {
+namespace tlv {
 
 BOOST_CONCEPT_ASSERT((ndn::WireEncodable<LsdbStatus>));
 BOOST_CONCEPT_ASSERT((ndn::WireDecodable<LsdbStatus>));
@@ -45,6 +45,57 @@
   wireDecode(block);
 }
 
+LsdbStatus&
+LsdbStatus::addAdjacencyLsa(const AdjacencyLsa& adjacencyLsa)
+{
+  m_adjacencyLsas.push_back(adjacencyLsa);
+  m_wire.reset();
+  m_hasAdjacencyLsas = true;
+  return *this;
+}
+
+LsdbStatus&
+LsdbStatus::clearAdjacencyLsas()
+{
+  m_adjacencyLsas.clear();
+  m_hasAdjacencyLsas = false;
+  return *this;
+}
+
+LsdbStatus&
+LsdbStatus::addCoordinateLsa(const CoordinateLsa& coordinateLsa)
+{
+  m_coordinateLsas.push_back(coordinateLsa);
+  m_wire.reset();
+  m_hasCoordinateLsas = true;
+  return *this;
+}
+
+LsdbStatus&
+LsdbStatus::clearCoordinateLsas()
+{
+  m_coordinateLsas.clear();
+  m_hasCoordinateLsas = false;
+  return *this;
+}
+
+LsdbStatus&
+LsdbStatus::addNameLsa(const NameLsa& nameLsa)
+{
+  m_nameLsas.push_back(nameLsa);
+  m_wire.reset();
+  m_hasNameLsas = true;
+  return *this;
+}
+
+LsdbStatus&
+LsdbStatus::clearNameLsas()
+{
+  m_nameLsas.clear();
+  m_hasNameLsas = false;
+  return *this;
+}
+
 template<ndn::encoding::Tag TAG>
 size_t
 LsdbStatus::wireEncode(ndn::EncodingImpl<TAG>& block) const
@@ -72,6 +123,8 @@
   return totalLength;
 }
 
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(LsdbStatus);
+
 template size_t
 LsdbStatus::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
 
@@ -113,7 +166,7 @@
     std::stringstream error;
     error << "Expected LsdbStatus Block, but Block is of a different type: #"
           << m_wire.type();
-    throw Error(error.str());
+    BOOST_THROW_EXCEPTION(Error(error.str()));
   }
 
   m_wire.parse();
@@ -139,7 +192,7 @@
     std::stringstream error;
     error << "Expected the end of elements, but Block is of a different type: #"
           << val->type();
-    throw Error(error.str());
+    BOOST_THROW_EXCEPTION(Error(error.str()));
   }
 }
 
diff --git a/src/tlv/lsdb-status.hpp b/src/tlv/lsdb-status.hpp
index fb494e6..b144ae2 100644
--- a/src/tlv/lsdb-status.hpp
+++ b/src/tlv/lsdb-status.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -37,15 +37,14 @@
 namespace nlsr {
 namespace tlv {
 
-/*!
-   \brief Data abstraction for LsdbStatus
-
-   LsdbStatus := LSDB-STATUS-TYPE TLV-LENGTH
-                   AdjacencyLsa*
-                   CoordinateLsa*
-                   NameLsa*
-
-   \sa https://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
+/*! \brief Data abstraction for LsdbStatus
+ *
+ *  LsdbStatus := LSDB-STATUS-TYPE TLV-LENGTH
+ *                  AdjacencyLsa*
+ *                  CoordinateLsa*
+ *                  NameLsa*
+ *
+ * \sa https://redmine.named-data.net/projects/nlsr/wiki/LSDB_DataSet
  */
 class LsdbStatus
 {
@@ -76,21 +75,10 @@
   }
 
   LsdbStatus&
-  addAdjacencyLsa(const AdjacencyLsa& adjacencyLsa)
-  {
-    m_adjacencyLsas.push_back(adjacencyLsa);
-    m_wire.reset();
-    m_hasAdjacencyLsas = true;
-    return *this;
-  }
+  addAdjacencyLsa(const AdjacencyLsa& adjacencyLsa);
 
   LsdbStatus&
-  clearAdjacencyLsas()
-  {
-    m_adjacencyLsas.clear();
-    m_hasAdjacencyLsas = false;
-    return *this;
-  }
+  clearAdjacencyLsas();
 
   bool
   hasAdjacencyLsas()
@@ -105,21 +93,10 @@
   }
 
   LsdbStatus&
-  addCoordinateLsa(const CoordinateLsa& coordinateLsa)
-  {
-    m_coordinateLsas.push_back(coordinateLsa);
-    m_wire.reset();
-    m_hasCoordinateLsas = true;
-    return *this;
-  }
+  addCoordinateLsa(const CoordinateLsa& coordinateLsa);
 
   LsdbStatus&
-  clearCoordinateLsas()
-  {
-    m_coordinateLsas.clear();
-    m_hasCoordinateLsas = false;
-    return *this;
-  }
+  clearCoordinateLsas();
 
   bool
   hasCoordinateLsas()
@@ -134,21 +111,10 @@
   }
 
   LsdbStatus&
-  addNameLsa(const NameLsa& nameLsa)
-  {
-    m_nameLsas.push_back(nameLsa);
-    m_wire.reset();
-    m_hasNameLsas = true;
-    return *this;
-  }
+  addNameLsa(const NameLsa& nameLsa);
 
   LsdbStatus&
-  clearNameLsas()
-  {
-    m_nameLsas.clear();
-    m_hasNameLsas = false;
-    return *this;
-  }
+  clearNameLsas();
 
   bool
   hasNameLsas()
diff --git a/src/tlv/nexthop.cpp b/src/tlv/nexthop.cpp
new file mode 100644
index 0000000..79b6e97
--- /dev/null
+++ b/src/tlv/nexthop.cpp
@@ -0,0 +1,136 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "nexthop.hpp"
+#include "tlv-nlsr.hpp"
+
+#include <ndn-cxx/util/concepts.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+namespace nlsr {
+namespace tlv {
+
+BOOST_CONCEPT_ASSERT((ndn::WireEncodable<NextHop>));
+BOOST_CONCEPT_ASSERT((ndn::WireDecodable<NextHop>));
+static_assert(std::is_base_of<ndn::tlv::Error, NextHop::Error>::value,
+              "NextHop::Error must inherit from tlv::Error");
+
+NextHop::NextHop()
+  : m_cost(0)
+{
+}
+
+NextHop::NextHop(const ndn::Block& block)
+{
+  wireDecode(block);
+}
+
+template<ndn::encoding::Tag TAG>
+size_t
+NextHop::wireEncode(ndn::EncodingImpl<TAG>& block) const
+{
+  size_t totalLength = 0;
+
+  const uint8_t* doubleBytes = reinterpret_cast<const uint8_t*>(&m_cost);
+  totalLength += block.prependByteArrayBlock(ndn::tlv::nlsr::Double, doubleBytes, 8);
+
+  totalLength += block.prependByteArrayBlock(
+    ndn::tlv::nlsr::Uri, reinterpret_cast<const uint8_t*>(m_uri.c_str()), m_uri.size());
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(ndn::tlv::nlsr::NextHop);
+
+  return totalLength;
+}
+
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(NextHop);
+
+template size_t
+NextHop::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
+
+template size_t
+NextHop::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+
+const ndn::Block&
+NextHop::wireEncode() const
+{
+  if (m_wire.hasWire()) {
+    return m_wire;
+  }
+
+  ndn::EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  ndn::EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+
+  return m_wire;
+}
+
+void
+NextHop::wireDecode(const ndn::Block& wire)
+{
+  m_uri = "";
+  m_cost = 0;
+
+  m_wire = wire;
+
+  if (m_wire.type() != ndn::tlv::nlsr::NextHop) {
+    std::stringstream error;
+    error << "Expected NextHop Block, but Block is of a different type: #"
+          << m_wire.type();
+    BOOST_THROW_EXCEPTION(Error(error.str()));
+  }
+
+  m_wire.parse();
+
+  ndn::Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::Uri) {
+    m_uri.assign(reinterpret_cast<const char*>(val->value()), val->value_size());
+    ++val;
+  }
+  else {
+    BOOST_THROW_EXCEPTION(Error("Missing required Uri field"));
+  }
+
+  if (val != val->elements_end() && val->type() == ndn::tlv::nlsr::Double) {
+    m_cost = *reinterpret_cast<const double*>(val->value());
+    ++val;
+  }
+  else {
+    BOOST_THROW_EXCEPTION(Error("HyperbolicCost: Missing required Double field"));
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const NextHop& nexthop)
+{
+  os << "NextHop("
+     << "Uri: " << nexthop.getUri() << ", "<< "Cost: " << nexthop.getCost() << ")" << std::endl;
+
+  return os;
+}
+
+} // namespace tlv
+} // namespace nlsr
diff --git a/src/tlv/nexthop.hpp b/src/tlv/nexthop.hpp
new file mode 100644
index 0000000..03666cc
--- /dev/null
+++ b/src/tlv/nexthop.hpp
@@ -0,0 +1,112 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_TLV_NEXTHOP_HPP
+#define NLSR_TLV_NEXTHOP_HPP
+
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/name.hpp>
+#include <boost/throw_exception.hpp>
+
+namespace nlsr {
+namespace tlv {
+
+/*! \brief Data abstraction for Nexthop
+ *
+ *   NextHop := NEXTHOP-TYPE TLV-LENGTH
+ *                Uri
+ *                Cost
+ *
+ * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_Dataset
+ */
+class NextHop
+{
+public:
+  class Error : public ndn::tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : ndn::tlv::Error(what)
+    {
+    }
+  };
+
+  NextHop();
+
+  explicit
+  NextHop(const ndn::Block& block);
+
+  const std::string&
+  getUri() const
+  {
+    return m_uri;
+  }
+
+  NextHop&
+  setUri(const std::string& uri)
+  {
+    m_uri = uri;
+    m_wire.reset();
+    return *this;
+  }
+
+  double
+  getCost() const
+  {
+    return m_cost;
+  }
+
+  NextHop&
+  setCost(double cost)
+  {
+    m_cost = cost;
+    m_wire.reset();
+    return *this;
+  }
+
+  template<ndn::encoding::Tag TAG>
+  size_t
+  wireEncode(ndn::EncodingImpl<TAG>& block) const;
+
+  const ndn::Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const ndn::Block& wire);
+
+private:
+  std::string m_uri;
+  double m_cost;
+
+  mutable ndn::Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const NextHop& nexthop);
+
+} // namespace tlv
+} // namespace nlsr
+
+#endif // NLSR_TLV_NEXTHOP_HPP
diff --git a/src/tlv/routing-table-entry.cpp b/src/tlv/routing-table-entry.cpp
new file mode 100644
index 0000000..39405af
--- /dev/null
+++ b/src/tlv/routing-table-entry.cpp
@@ -0,0 +1,172 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "routing-table-entry.hpp"
+#include "tlv-nlsr.hpp"
+
+#include <ndn-cxx/util/concepts.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+namespace nlsr {
+namespace tlv {
+
+BOOST_CONCEPT_ASSERT((ndn::WireEncodable<RoutingTable>));
+BOOST_CONCEPT_ASSERT((ndn::WireDecodable<RoutingTable>));
+static_assert(std::is_base_of<ndn::tlv::Error, RoutingTable::Error>::value,
+              "RoutingTable::Error must inherit from tlv::Error");
+
+RoutingTable::RoutingTable()
+  : m_hasNexthops(false)
+{
+}
+
+RoutingTable::RoutingTable(const ndn::Block& block)
+{
+  wireDecode(block);
+}
+
+bool
+RoutingTable::hasNexthops() const
+{
+  return m_hasNexthops;
+}
+
+RoutingTable&
+RoutingTable::addNexthops(const NextHop& nexthop)
+{
+  m_nexthops.push_back(nexthop);
+  m_wire.reset();
+  m_hasNexthops = true;
+  return *this;
+}
+
+RoutingTable&
+RoutingTable::clearNexthops()
+{
+  m_nexthops.clear();
+  m_hasNexthops = false;
+  return *this;
+}
+
+template<ndn::encoding::Tag TAG>
+size_t
+RoutingTable::wireEncode(ndn::EncodingImpl<TAG>& block) const
+{
+  size_t totalLength = 0;
+
+  for (std::list<NextHop>::const_reverse_iterator it = m_nexthops.rbegin();
+       it != m_nexthops.rend(); ++it) {
+    totalLength += it->wireEncode(block);
+  }
+
+  totalLength += m_des.wireEncode(block);
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(ndn::tlv::nlsr::RouteTableEntry);
+
+  return totalLength;
+}
+
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTable);
+
+template size_t
+RoutingTable::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& encoder) const;
+
+template size_t
+RoutingTable::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& encoder) const;
+
+const ndn::Block&
+RoutingTable::wireEncode() const
+{
+  if (m_wire.hasWire()) {
+    return m_wire;
+  }
+
+  ndn::EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  ndn::EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+
+  return m_wire;
+}
+
+void
+RoutingTable::wireDecode(const ndn::Block& wire)
+{
+  m_hasNexthops = false;
+  m_nexthops.clear();
+
+  m_wire = wire;
+
+  if (m_wire.type() != ndn::tlv::nlsr::RouteTableEntry) {
+    std::stringstream error;
+    error << "Expected RoutingTable Block, but Block is of a different type: #"
+          << m_wire.type();
+    BOOST_THROW_EXCEPTION(Error(error.str()));
+  }
+
+  m_wire.parse();
+
+  ndn::Block::element_const_iterator val = m_wire.elements_begin();
+
+  if (val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::Destination) {
+    m_des.wireDecode(*val);
+    ++val;
+  }
+  else {
+    BOOST_THROW_EXCEPTION(Error("Missing required destination field"));
+  }
+
+  for (; val != m_wire.elements_end(); ++val) {
+    if (val->type() == ndn::tlv::nlsr::NextHop) {
+      m_nexthops.push_back(NextHop(*val));
+      m_hasNexthops = true;
+    }
+    else {
+      std::stringstream error;
+      error << "Expected NextHop Block, but Block is of a different type: #"
+            << m_wire.type();
+      BOOST_THROW_EXCEPTION(Error(error.str()));
+    }
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const RoutingTable& routingtable)
+{
+  os << "Routing Table: " << std::endl;
+  os << routingtable.getDestination() << std::endl;
+  os << "Nexthops: NexthopList(" << std::endl;
+
+  for (const auto& rtentry : routingtable) {
+    os << rtentry << std::endl;
+  }
+
+  os << ")";
+
+  return os;
+}
+
+} // namespace tlv
+} // namespace nlsr
diff --git a/src/tlv/routing-table-entry.hpp b/src/tlv/routing-table-entry.hpp
new file mode 100644
index 0000000..176becb
--- /dev/null
+++ b/src/tlv/routing-table-entry.hpp
@@ -0,0 +1,154 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_TLV_ROUTING_TABLE_ENTRY_HPP
+#define NLSR_TLV_ROUTING_TABLE_ENTRY_HPP
+
+#include "destination.hpp"
+#include "nexthop.hpp"
+
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/name.hpp>
+
+#include <list>
+
+namespace nlsr {
+namespace tlv {
+
+/*! \brief Data abstraction for RouteTableInfo
+ *
+ *   RouteTableInfo := ROUTINGTABLE-TYPE TLV-LENGTH
+ *                       Destination
+ *                       NexthopList*
+ *
+ * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_DataSet
+ */
+class RoutingTable
+{
+public:
+  class Error : public ndn::tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : ndn::tlv::Error(what)
+    {
+    }
+  };
+
+  typedef std::list<NextHop> HopList;
+  typedef HopList::const_iterator const_iterator;
+
+  RoutingTable();
+
+  explicit
+  RoutingTable(const ndn::Block& block);
+
+  const Destination&
+  getDestination() const
+  {
+    return m_des;
+  }
+
+  RoutingTable&
+  setDestination(const Destination& des)
+  {
+    m_des = des;
+    m_wire.reset();
+    return *this;
+  }
+
+  uint64_t
+  getRtSize() const
+  {
+    return m_size;
+  }
+
+  RoutingTable&
+  setRtSize(uint64_t size)
+  {
+    m_size = size;
+    m_wire.reset();
+    return *this;
+  }
+
+  bool
+  hasNexthops() const;
+
+  const std::list<NextHop>&
+  getNextHops() const
+  {
+    return m_nexthops;
+  }
+
+  RoutingTable&
+  addNexthops(const NextHop& nexthop);
+
+  RoutingTable&
+  clearNexthops();
+
+  template<ndn::encoding::Tag TAG>
+  size_t
+  wireEncode(ndn::EncodingImpl<TAG>& block) const;
+
+  const ndn::Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const ndn::Block& wire);
+
+  const_iterator
+  begin() const;
+
+  const_iterator
+  end() const;
+
+private:
+  Destination m_des;
+  uint64_t m_size;
+  bool m_hasNexthops;
+  HopList m_nexthops;
+
+  mutable ndn::Block m_wire;
+};
+
+inline RoutingTable::const_iterator
+RoutingTable::begin() const
+{
+  return m_nexthops.begin();
+}
+
+inline RoutingTable::const_iterator
+RoutingTable::end() const
+{
+  return m_nexthops.end();
+}
+
+std::ostream&
+operator<<(std::ostream& os, const RoutingTable& routetable);
+
+} // namespace tlv
+} // namespace nlsr
+
+#endif // NLSR_TLV_ROUTING_TABLE_ENTRY_HPP
diff --git a/src/tlv/routing-table-status.cpp b/src/tlv/routing-table-status.cpp
new file mode 100644
index 0000000..d2c8a55
--- /dev/null
+++ b/src/tlv/routing-table-status.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "routing-table-status.hpp"
+#include "tlv-nlsr.hpp"
+
+#include <ndn-cxx/util/concepts.hpp>
+#include <ndn-cxx/encoding/block-helpers.hpp>
+
+namespace nlsr {
+namespace tlv {
+
+BOOST_CONCEPT_ASSERT((ndn::WireEncodable<RoutingTableStatus>));
+BOOST_CONCEPT_ASSERT((ndn::WireDecodable<RoutingTableStatus>));
+static_assert(std::is_base_of<ndn::tlv::Error, RoutingTableStatus::Error>::value,
+              "RTStatus::Error must inherit from tlv::Error");
+
+RoutingTableStatus::RoutingTableStatus()
+  : m_hasRoutingtable(false)
+{
+}
+
+RoutingTableStatus::RoutingTableStatus(const ndn::Block& block)
+{
+  wireDecode(block);
+}
+
+RoutingTableStatus&
+RoutingTableStatus::addRoutingTable(const RoutingTable& routetable)
+{
+  m_routingtables.push_back(routetable);
+  m_wire.reset();
+  m_hasRoutingtable = true;
+  return *this;
+}
+
+RoutingTableStatus&
+RoutingTableStatus::clearRoutingTable()
+{
+  m_routingtables.clear();
+  m_hasRoutingtable = false;
+  return *this;
+}
+
+bool
+RoutingTableStatus::hasRoutingTable()
+{
+  return m_hasRoutingtable;
+}
+
+template<ndn::encoding::Tag TAG>
+size_t
+RoutingTableStatus::wireEncode(ndn::EncodingImpl<TAG>& block) const
+{
+  size_t totalLength = 0;
+
+  for (std::list<RoutingTable>::const_reverse_iterator it = m_routingtables.rbegin();
+       it != m_routingtables.rend(); ++it) {
+    totalLength += it->wireEncode(block);
+  }
+
+  totalLength += block.prependVarNumber(totalLength);
+  totalLength += block.prependVarNumber(ndn::tlv::nlsr::RoutingTable);
+
+  return totalLength;
+}
+
+NDN_CXX_DECLARE_WIRE_ENCODE_INSTANTIATIONS(RoutingTableStatus);
+
+template size_t
+RoutingTableStatus::wireEncode<ndn::encoding::EncoderTag>(ndn::EncodingImpl<ndn::encoding::EncoderTag>& block) const;
+
+template size_t
+RoutingTableStatus::wireEncode<ndn::encoding::EstimatorTag>(ndn::EncodingImpl<ndn::encoding::EstimatorTag>& block) const;
+
+const ndn::Block&
+RoutingTableStatus::wireEncode() const
+{
+  if (m_wire.hasWire()) {
+    return m_wire;
+  }
+
+  ndn::EncodingEstimator estimator;
+  size_t estimatedSize = wireEncode(estimator);
+
+  ndn::EncodingBuffer buffer(estimatedSize, 0);
+  wireEncode(buffer);
+
+  m_wire = buffer.block();
+
+  return m_wire;
+}
+
+void
+RoutingTableStatus::wireDecode(const ndn::Block& wire)
+{
+  m_routingtables.clear();
+
+  m_hasRoutingtable = false;
+
+  m_wire = wire;
+
+  if (m_wire.type() != ndn::tlv::nlsr::RoutingTable) {
+    std::stringstream error;
+    error << "Expected RoutingTableStatus Block, but Block is of a different type: #"
+          << m_wire.type();
+    BOOST_THROW_EXCEPTION(Error(error.str()));
+  }
+
+  m_wire.parse();
+
+  ndn::Block::element_const_iterator val = m_wire.elements_begin();
+
+  for (; val != m_wire.elements_end() && val->type() == ndn::tlv::nlsr::RouteTableEntry; ++val) {
+    m_routingtables.push_back(RoutingTable(*val));
+    m_hasRoutingtable = true;
+  }
+
+  if (val != m_wire.elements_end()) {
+    std::stringstream error;
+    error << "Expected the end of elements, but Block is of a different type: #"
+          << val->type();
+    BOOST_THROW_EXCEPTION(Error(error.str()));
+  }
+}
+
+std::ostream&
+operator<<(std::ostream& os, const RoutingTableStatus& rtStatus)
+{
+  os << "Routing Table Status: " << std::endl;;
+
+  bool isFirst = true;
+
+  for (const auto& routingtable : rtStatus.getRoutingtable()) {
+    if (isFirst) {
+      isFirst = false;
+    }
+    else {
+      os << ", ";
+    }
+
+    os << routingtable;
+  }
+
+  return os;
+}
+
+} // namespace tlv
+} // namespace nlsr
diff --git a/src/tlv/routing-table-status.hpp b/src/tlv/routing-table-status.hpp
new file mode 100644
index 0000000..1ce3497
--- /dev/null
+++ b/src/tlv/routing-table-status.hpp
@@ -0,0 +1,104 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#ifndef NLSR_TLV_ROUTING_TABLE_STATUS_HPP
+#define NLSR_TLV_ROUTING_TABLE_STATUS_HPP
+
+#include "routing-table-entry.hpp"
+#include "destination.hpp"
+
+#include <ndn-cxx/util/time.hpp>
+#include <ndn-cxx/encoding/block.hpp>
+#include <ndn-cxx/encoding/encoding-buffer.hpp>
+#include <ndn-cxx/encoding/tlv.hpp>
+#include <ndn-cxx/name.hpp>
+
+#include <list>
+
+namespace nlsr {
+namespace tlv {
+
+/*! \brief Data abstraction for routing table status
+ *
+ * RtStatus := RT-STATUS-TYPE TLV-LENGTH
+ *              RouteTableInfo*
+ *
+ * \sa https://redmine.named-data.net/projects/nlsr/wiki/Routing_Table_Dataset
+ */
+class RoutingTableStatus
+{
+public:
+  class Error : public ndn::tlv::Error
+  {
+  public:
+    explicit
+    Error(const std::string& what)
+      : ndn::tlv::Error(what)
+    {
+    }
+  };
+
+  typedef std::list<RoutingTable> RTList;
+
+  RoutingTableStatus();
+
+  explicit
+  RoutingTableStatus(const ndn::Block& block);
+
+  const std::list<RoutingTable>&
+  getRoutingtable() const
+  {
+    return m_routingtables;
+  }
+
+  RoutingTableStatus&
+  addRoutingTable(const RoutingTable& routeTable);
+
+  RoutingTableStatus&
+  clearRoutingTable();
+
+  bool
+  hasRoutingTable();
+
+  template<ndn::encoding::Tag TAG>
+  size_t
+  wireEncode(ndn::EncodingImpl<TAG>& block) const;
+
+  const ndn::Block&
+  wireEncode() const;
+
+  void
+  wireDecode(const ndn::Block& wire);
+
+private:
+  RTList m_routingtables;
+  bool m_hasRoutingtable;
+
+  mutable ndn::Block m_wire;
+};
+
+std::ostream&
+operator<<(std::ostream& os, const RoutingTableStatus& rtStatus);
+
+} // namespace tlv
+} // namespace nlsr
+
+#endif // NLSR_TLV_ROUTING_TABLE_STATUS_HPP
diff --git a/src/tlv/tlv-nlsr.hpp b/src/tlv/tlv-nlsr.hpp
index 4a52b1b..3960eb0 100644
--- a/src/tlv/tlv-nlsr.hpp
+++ b/src/tlv/tlv-nlsr.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -47,7 +47,11 @@
   LsdbStatus       = 138,
   ExpirationPeriod = 139,
   Cost             = 140,
-  Uri              = 141
+  Uri              = 141,
+  Destination      = 142,
+  NextHop          = 143,
+  RoutingTable     = 144,
+  RouteTableEntry  = 145
 };
 
 } // namespace nlsr
diff --git a/tests/publisher/publisher-fixture.hpp b/tests/publisher/publisher-fixture.hpp
index 4b702fc..896e7b3 100644
--- a/tests/publisher/publisher-fixture.hpp
+++ b/tests/publisher/publisher-fixture.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,7 +22,7 @@
 #ifndef NLSR_PUBLISHER_FIXTURE_HPP
 #define NLSR_PUBLISHER_FIXTURE_HPP
 
-#include "publisher/lsdb-dataset-interest-handler.hpp"
+#include "publisher/dataset-interest-handler.hpp"
 #include "nlsr.hpp"
 
 #include "../boost-test.hpp"
@@ -48,6 +48,7 @@
     : face(m_ioService, m_keyChain, {true, true})
     , nlsr(m_ioService, m_scheduler, face, m_keyChain)
     , lsdb(nlsr.getLsdb())
+    , rt1(nlsr.getRoutingTable())
   {
     INIT_LOGGERS("/tmp/", "TRACE");
     nlsr.getConfParameter().setNetwork("/ndn");
@@ -100,6 +101,13 @@
     }
   }
 
+  NextHop
+  createNextHop(const std::string& faceUri, double cost)
+  {
+    NextHop nexthop(faceUri, cost);
+    return nexthop;
+  }
+
   CoordinateLsa
   createCoordinateLsa(const std::string& origin, double radius, std::vector<double> angle)
   {
@@ -159,6 +167,7 @@
   Lsdb& lsdb;
 
   ndn::security::pib::Identity routerId;
+  RoutingTable& rt1;
 };
 
 } // namespace test
diff --git a/tests/publisher/test-lsdb-dataset-interest-handler.cpp b/tests/publisher/test-dataset-interest-handler.cpp
similarity index 81%
rename from tests/publisher/test-lsdb-dataset-interest-handler.cpp
rename to tests/publisher/test-dataset-interest-handler.cpp
index cd9fcf3..ccd3b64 100644
--- a/tests/publisher/test-lsdb-dataset-interest-handler.cpp
+++ b/tests/publisher/test-dataset-interest-handler.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -19,7 +19,7 @@
  * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
  **/
 
-#include "publisher/lsdb-dataset-interest-handler.hpp"
+#include "publisher/dataset-interest-handler.hpp"
 #include "tests/test-common.hpp"
 #include "tlv/tlv-nlsr.hpp"
 
@@ -28,6 +28,8 @@
 
 #include <ndn-cxx/mgmt/nfd/control-response.hpp>
 
+#include <iostream>
+
 namespace nlsr {
 namespace test {
 
@@ -36,6 +38,7 @@
                        std::function<bool(const ndn::Block&)> isSameType)
 {
   face.processEvents(ndn::time::milliseconds(30));
+
   BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
 
   ndn::Block parser(face.sentData[0].getContent());
@@ -50,17 +53,6 @@
   face.sentData.clear();
 }
 
-void
-checkErrorResponse(ndn::util::DummyClientFace& face, uint64_t expectedCode)
-{
-  BOOST_REQUIRE_EQUAL(face.sentData.size(), 1);
-
-  ndn::nfd::ControlResponse response(face.sentData[0].getContent().blockFromValue());
-  BOOST_CHECK_EQUAL(response.getCode(), expectedCode);
-
-  face.sentData.clear();
-}
-
 BOOST_FIXTURE_TEST_SUITE(PublisherTestLsdbDatasetInterestHandler, PublisherFixture)
 
 BOOST_AUTO_TEST_CASE(Localhost)
@@ -83,6 +75,14 @@
   nameLsa.addName("/RouterA/name1");
   lsdb.installNameLsa(nameLsa);
 
+  // Install routing table
+  RoutingTableEntry rte1("desrouter1");
+  const ndn::Name& DEST_ROUTER = rte1.getDestination();
+
+  NextHop nh = createNextHop("udp://face-test1", 10);
+
+  rt1.addNextHop(DEST_ROUTER, nh);
+
   // Request adjacency LSAs
   face.receive(ndn::Interest(ndn::Name("/localhost/nlsr/lsdb").append("adjacencies")));
   processDatasetInterest(face,
@@ -98,10 +98,11 @@
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
 
-  // Request LSDB Status
-  face.receive(ndn::Interest(ndn::Name("/localhost/nlsr/lsdb").append("list")));
+  // Request Routing Table
+  face.receive(ndn::Interest(ndn::Name("/localhost/nlsr/routing-table")));
   processDatasetInterest(face,
-    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
+    [] (const ndn::Block& block) {
+      return block.type() == ndn::tlv::nlsr::RouteTableEntry; });
 }
 
 
@@ -119,6 +120,14 @@
   CoordinateLsa coordinateLsa = createCoordinateLsa("/RouterA", 10.0, angles);
   lsdb.installCoordinateLsa(coordinateLsa);
 
+  //Install routing table
+  RoutingTableEntry rte1("desrouter1");
+  const ndn::Name& DEST_ROUTER = rte1.getDestination();
+
+  NextHop nh = createNextHop("udp://face-test1", 10);
+
+  rt1.addNextHop(DEST_ROUTER, nh);
+
   // Request adjacency LSAs
   face.receive(ndn::Interest(ndn::Name("/ndn/This/Router/lsdb").append("adjacencies")));
   processDatasetInterest(face,
@@ -134,10 +143,11 @@
   processDatasetInterest(face,
     [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::NameLsa; });
 
-  // Request LSDB Status
-  face.receive(ndn::Interest(ndn::Name("/ndn/This/Router/lsdb").append("list")));
+  // Request Routing Table
+  face.receive(ndn::Interest(ndn::Name("/ndn/This/Router/routing-table")));
   processDatasetInterest(face,
-    [] (const ndn::Block& block) { return block.type() == ndn::tlv::nlsr::LsdbStatus; });
+    [] (const ndn::Block& block) {
+      return block.type() == ndn::tlv::nlsr::RouteTableEntry; });
 }
 
 BOOST_AUTO_TEST_SUITE_END()
diff --git a/tests/test-nlsr.cpp b/tests/test-nlsr.cpp
index 180c295..5c91312 100644
--- a/tests/test-nlsr.cpp
+++ b/tests/test-nlsr.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -362,7 +362,7 @@
 {
   nlsr.initialize();
 
-  BOOST_CHECK_EQUAL(nlsr.getLsdbDatasetHandler().getRouterNameCommandPrefix(),
+  BOOST_CHECK_EQUAL(nlsr.getDatasetHandler().getRouterNameCommandPrefix(),
                     ndn::Name("/ndn/site/%C1.Router/this-router/lsdb"));
 }
 
diff --git a/tests/tlv/test-destination.cpp b/tests/tlv/test-destination.cpp
new file mode 100644
index 0000000..b74120d
--- /dev/null
+++ b/tests/tlv/test-destination.cpp
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "tlv/destination.hpp"
+
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace tlv {
+namespace test {
+
+BOOST_AUTO_TEST_SUITE(TlvTestDes)
+
+const uint8_t DesData[] =
+{
+  // Header
+  0x8e, 0x13,
+  // Routername 746573742f646573742f746c76
+  0x07, 0x11, 0x08, 0x04, 0x74, 0x65, 0x73, 0x74, 0x08, 0x04, 0x64, 0x65, 0x73, 0x74,
+  0x08, 0x03, 0x74, 0x6c, 0x76
+};
+
+BOOST_AUTO_TEST_CASE(DesEncode)
+{
+  Destination des1;
+  des1.setName("/test/dest/tlv");
+
+  const ndn::Block& wire = des1.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(DesData,
+                                  DesData + sizeof(DesData),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(DesDecode)
+{
+  Destination des1;
+
+  des1.wireDecode(ndn::Block(DesData, sizeof(DesData)));
+
+  ndn::Name DEST_NAME = ndn::Name("/test/dest/tlv");
+  BOOST_REQUIRE_EQUAL(des1.getName(), DEST_NAME);
+}
+
+BOOST_AUTO_TEST_CASE(DesOutputStream)
+{
+  Destination des1;
+  des1.setName("/test/dest/tlv");
+
+  std::ostringstream os;
+  os << des1;
+
+  BOOST_CHECK_EQUAL(os.str(), "Destination: /test/dest/tlv");
+}
+
+BOOST_AUTO_TEST_CASE(DesMake)
+{
+  RoutingTableEntry rte("/test/dest/tlv");
+
+  std::shared_ptr<Destination> des = makeDes(rte);
+  BOOST_CHECK_EQUAL(des->getName(), rte.getDestination());
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace tlv
+} // namespace nlsr
diff --git a/tests/tlv/test-nexthops.cpp b/tests/tlv/test-nexthops.cpp
new file mode 100644
index 0000000..a0472e8
--- /dev/null
+++ b/tests/tlv/test-nexthops.cpp
@@ -0,0 +1,80 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "tlv/nexthop.hpp"
+
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace tlv {
+namespace test {
+
+BOOST_AUTO_TEST_SUITE(TlvTestNexthops)
+
+const uint8_t NexthopData[] =
+{
+  // Header
+  0x8f, 0x1d,
+  // Uri
+  0x8d, 0x11, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x2f, 0x74, 0x6c, 0x76,
+  // Cost
+  0x86, 0x08, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfa, 0x3f
+};
+
+BOOST_AUTO_TEST_CASE(NexthopEncode)
+{
+  NextHop nexthops1;
+  nexthops1.setUri("/test/nexthop/tlv");
+  nexthops1.setCost(1.65);
+
+  const ndn::Block& wire = nexthops1.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(NexthopData,
+                                  NexthopData + sizeof(NexthopData),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(NexthopDecode)
+{
+  NextHop nexthops1;
+
+  nexthops1.wireDecode(ndn::Block(NexthopData, sizeof(NexthopData)));
+
+  BOOST_REQUIRE_EQUAL(nexthops1.getUri(), "/test/nexthop/tlv");
+  BOOST_REQUIRE_EQUAL(nexthops1.getCost(), 1.65);
+}
+
+BOOST_AUTO_TEST_CASE(AdjacencyOutputStream)
+{
+  NextHop nexthops1;
+  nexthops1.setUri("/test/nexthop/tlv");
+  nexthops1.setCost(99);
+
+  std::ostringstream os;
+  os << nexthops1;
+  BOOST_CHECK_EQUAL(os.str(), "NextHop(Uri: /test/nexthop/tlv, Cost: 99)\n");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace tlv
+} // namespace nlsr
diff --git a/tests/tlv/test-routing-table-entry.cpp b/tests/tlv/test-routing-table-entry.cpp
new file mode 100644
index 0000000..5b882a2
--- /dev/null
+++ b/tests/tlv/test-routing-table-entry.cpp
@@ -0,0 +1,192 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "tlv/routing-table-entry.hpp"
+
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace tlv {
+namespace test {
+
+BOOST_AUTO_TEST_SUITE(TlvTestRoutingTableEntry)
+
+const uint8_t RoutingTableEntryWithNexthopsData[] =
+{
+  // Header
+  0x91, 0x37,
+  // Destination
+  0x8e, 0x09, 0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31,
+  // Nexthop
+  0x8f, 0x14, 0x8d, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70,
+  0x31, 0x86, 0x08, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfa, 0x3f,
+  // Nexthop
+  0x8f, 0x14, 0x8d, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70,
+  0x32, 0x86, 0x08, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfa, 0x3f
+};
+
+const uint8_t RoutingTableEntryWithoutNexthopsData[] =
+{
+  // Header
+  0x91, 0x0b,
+  // Destination
+  0x8e, 0x09, 0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31
+};
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryEncodeWithNexthops)
+{
+  RoutingTable rt;
+
+  Destination des1;
+  des1.setName("dest1");
+  rt.setDestination(des1);
+
+  NextHop nexthops1;
+  nexthops1.setUri("nexthop1");
+  nexthops1.setCost(1.65);
+  rt.addNexthops(nexthops1);
+
+  NextHop nexthops2;
+  nexthops2.setUri("nexthop2");
+  nexthops2.setCost(1.65);
+  rt.addNexthops(nexthops2);
+
+  const ndn::Block& wire = rt.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(RoutingTableEntryWithNexthopsData,
+                                  RoutingTableEntryWithNexthopsData +
+                                    sizeof(RoutingTableEntryWithNexthopsData),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryDecodeWithNexthops)
+{
+  RoutingTable rt;
+
+  rt.wireDecode(ndn::Block(RoutingTableEntryWithNexthopsData,
+                                      sizeof(RoutingTableEntryWithNexthopsData)));
+
+  Destination des = rt.getDestination();
+  BOOST_CHECK_EQUAL(des.getName(), "dest1");
+
+  BOOST_CHECK_EQUAL(rt.hasNexthops(), true);
+  std::list<NextHop> nexthops = rt.getNextHops();
+  std::list<NextHop>::const_iterator it = nexthops.begin();
+  BOOST_CHECK_EQUAL(it->getUri(), "nexthop1");
+  BOOST_CHECK_EQUAL(it->getCost(), 1.65);
+
+  it++;
+  BOOST_CHECK_EQUAL(it->getUri(), "nexthop2");
+  BOOST_CHECK_EQUAL(it->getCost(), 1.65);
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryEncodeWithoutNexthops)
+{
+  RoutingTable rt;
+
+  Destination des1;
+  des1.setName("dest1");
+  rt.setDestination(des1);
+
+  const ndn::Block& wire = rt.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(RoutingTableEntryWithoutNexthopsData,
+                                  RoutingTableEntryWithoutNexthopsData +
+                                    sizeof(RoutingTableEntryWithoutNexthopsData),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryDecodeWithoutNexthops)
+{
+  RoutingTable rt;
+
+  rt.wireDecode(ndn::Block(RoutingTableEntryWithoutNexthopsData,
+                           sizeof(RoutingTableEntryWithoutNexthopsData)));
+
+  Destination des = rt.getDestination();
+  BOOST_CHECK_EQUAL(des.getName(), "dest1");
+
+  BOOST_CHECK_EQUAL(rt.hasNexthops(), false);
+}
+
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryClear)
+{
+  RoutingTable rt;
+  Destination des1;
+  des1.setName("dest1");
+  rt.setDestination(des1);
+
+  NextHop nexthops1;
+  nexthops1.setUri("nexthop1");
+  nexthops1.setCost(99);
+  rt.addNexthops(nexthops1);
+
+  BOOST_CHECK_EQUAL(rt.getNextHops().size(), 1);
+
+  std::list<NextHop> nexthops = rt.getNextHops();
+  std::list<NextHop>::const_iterator it = nexthops.begin();
+  BOOST_CHECK_EQUAL(it->getUri(), "nexthop1");
+  BOOST_CHECK_EQUAL(it->getCost(), 99);
+
+  rt.clearNexthops();
+  BOOST_CHECK_EQUAL(rt.getNextHops().size(), 0);
+
+  NextHop nexthops2;
+  nexthops2.setUri("nexthop2");
+  nexthops2.setCost(99);
+  rt.addNexthops(nexthops2);
+
+  BOOST_CHECK_EQUAL(rt.getNextHops().size(), 1);
+
+  nexthops = rt.getNextHops();
+  it = nexthops.begin();
+  BOOST_CHECK_EQUAL(it->getUri(), "nexthop2");
+  BOOST_CHECK_EQUAL(it->getCost(), 99);
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableEntryOutputStream)
+{
+  RoutingTable rt;
+  Destination des1;
+  des1.setName("dest1");
+  rt.setDestination(des1);
+
+  NextHop nexthops1;
+  nexthops1.setUri("nexthop1");
+  nexthops1.setCost(99);
+  rt.addNexthops(nexthops1);
+
+  std::ostringstream os;
+  os << rt;
+
+  BOOST_CHECK_EQUAL(os.str(), "Routing Table: \n"
+                                  "Destination: /dest1\n"
+                                  "Nexthops: NexthopList(\n"
+                                  "NextHop(Uri: nexthop1, Cost: 99)\n"
+                                  "\n)");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace tlv
+} // namespace nlsr
diff --git a/tests/tlv/test-routing-table.cpp b/tests/tlv/test-routing-table.cpp
new file mode 100644
index 0000000..c4b798f
--- /dev/null
+++ b/tests/tlv/test-routing-table.cpp
@@ -0,0 +1,169 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2018,  The University of Memphis,
+ *                           Regents of the University of California,
+ *                           Arizona Board of Regents.
+ *
+ * This file is part of NLSR (Named-data Link State Routing).
+ * See AUTHORS.md for complete list of NLSR authors and contributors.
+ *
+ * NLSR is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Foundation,
+ * either version 3 of the License, or (at your option) any later version.
+ *
+ * NLSR 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
+ * NLSR, e.g., in COPYING.md file.  If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+#include "tlv/routing-table-status.hpp"
+
+#include "../boost-test.hpp"
+
+namespace nlsr {
+namespace tlv {
+namespace test {
+
+BOOST_AUTO_TEST_SUITE(TlvTestRoutingTable)
+
+const uint8_t RoutingTableData1[] =
+{
+  // Header
+  0x90, 0x22,
+  // Routing table entry
+  0x91, 0x20,
+    // Destination
+    0x8e, 0x09, 0x07, 0x07, 0x08, 0x05, 0x64, 0x65, 0x73, 0x74, 0x31,
+    // Nexthop
+    0x8f, 0x13, 0x8d, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x68, 0x6f, 0x70, 0x86, 0x08, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfa, 0x3f
+};
+
+const uint8_t RoutingTableData2[] =
+{
+  // Header
+  0x90, 0x00
+};
+
+BOOST_AUTO_TEST_CASE(RoutingTableEncode1)
+{
+  RoutingTableStatus rtStatus;
+
+  Destination des;
+  des.setName("dest1");
+
+  // RoutingtableEntry
+  RoutingTable rt;
+  rt.setDestination(des);
+
+  NextHop nexthops;
+  nexthops.setUri("nexthop");
+  nexthops.setCost(1.65);
+  rt.addNexthops(nexthops);
+
+  rtStatus.addRoutingTable(rt);
+
+  const ndn::Block& wire = rtStatus.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(RoutingTableData1,
+                                  RoutingTableData1 + sizeof(RoutingTableData1),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableEncode2)
+{
+  RoutingTableStatus rtStatus;
+
+  const ndn::Block& wire = rtStatus.wireEncode();
+
+  BOOST_REQUIRE_EQUAL_COLLECTIONS(RoutingTableData2,
+                                  RoutingTableData2 + sizeof(RoutingTableData2),
+                                  wire.begin(), wire.end());
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableDecode1)
+{
+  RoutingTableStatus rtStatus;
+
+  rtStatus.wireDecode(ndn::Block(RoutingTableData1, sizeof(RoutingTableData1)));
+
+  std::list<RoutingTable> rte = rtStatus.getRoutingtable();
+  std::list<RoutingTable>::const_iterator it1 = rte.begin();
+
+  Destination des1 = it1->getDestination();
+  BOOST_CHECK_EQUAL(des1.getName(), "dest1");
+
+  std::list<NextHop> nexthops = it1->getNextHops();
+  std::list<NextHop>::const_iterator it2 = nexthops.begin();
+  BOOST_CHECK_EQUAL(it2->getUri(), "nexthop");
+  BOOST_CHECK_EQUAL(it2->getCost(), 1.65);
+
+  BOOST_CHECK_EQUAL(rtStatus.hasRoutingTable(), true);
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableDecode2)
+{
+  RoutingTableStatus rtStatus;
+
+  rtStatus.wireDecode(ndn::Block(RoutingTableData2, sizeof(RoutingTableData2)));
+
+  BOOST_CHECK_EQUAL(rtStatus.hasRoutingTable(), false);
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableClear)
+{
+  RoutingTableStatus rtStatus;
+  Destination des;
+  des.setName("dest1");
+
+  // RoutingtableEntry
+  RoutingTable rt;
+  rt.setDestination(des);
+
+  NextHop nexthops;
+  nexthops.setUri("nexthop");
+  nexthops.setCost(1.65);
+  rt.addNexthops(nexthops);
+
+  rtStatus.addRoutingTable(rt);
+
+  BOOST_CHECK_EQUAL(rtStatus.hasRoutingTable(), true);
+  rtStatus.clearRoutingTable();
+  BOOST_CHECK_EQUAL(rtStatus.hasRoutingTable(), false);
+}
+
+BOOST_AUTO_TEST_CASE(RoutingTableOutputStream)
+{
+  RoutingTableStatus rtStatus;
+  Destination des;
+  des.setName("dest1");
+
+  // RoutingtableEntry
+  RoutingTable rt;
+  rt.setDestination(des);
+
+  NextHop nexthops;
+  nexthops.setUri("nexthop");
+  nexthops.setCost(99);
+  rt.addNexthops(nexthops);
+
+  rtStatus.addRoutingTable(rt);
+
+  std::ostringstream os;
+  os << rtStatus;
+
+  BOOST_CHECK_EQUAL(os.str(), "Routing Table Status: \n"
+                                "Routing Table: \n"
+                                  "Destination: /dest1\n"
+                                  "Nexthops: NexthopList(\n"
+                                  "NextHop(Uri: nexthop, Cost: 99)\n"
+                                  "\n)");
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
+} // namespace test
+} // namespace tlv
+} // namespace nlsr
diff --git a/tools/nlsrc.cpp b/tools/nlsrc.cpp
index 103fa26..db2de6a 100644
--- a/tools/nlsrc.cpp
+++ b/tools/nlsrc.cpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,7 +22,7 @@
 #include "nlsrc.hpp"
 
 #include "version.hpp"
-#include "src/publisher/lsdb-dataset-interest-handler.hpp"
+#include "src/publisher/dataset-interest-handler.hpp"
 
 #include <ndn-cxx/face.hpp>
 #include <ndn-cxx/data.hpp>
@@ -42,6 +42,8 @@
 const ndn::Name Nlsrc::LSDB_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("lsdb");
 const ndn::Name Nlsrc::NAME_UPDATE_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("prefix-update");
 
+const ndn::Name Nlsrc::RT_PREFIX = ndn::Name(Nlsrc::LOCALHOST_PREFIX).append("routing-table");
+
 const uint32_t Nlsrc::ERROR_CODE_TIMEOUT = 10060;
 const uint32_t Nlsrc::RESPONSE_CODE_SUCCESS = 200;
 
@@ -58,8 +60,12 @@
     "       -V print version and exit\n"
     "\n"
     "   COMMAND can be one of the following:\n"
+    "       lsdb\n"
+    "           display NLSR lsdb status\n"
+    "       routing\n"
+    "           display routing table status\n"
     "       status\n"
-    "           display NLSR status\n"
+    "           display all NLSR status (lsdb & routingtable)\n"
     "       advertise name\n"
     "           advertise a name prefix through NLSR\n"
     "       withdraw name\n"
@@ -68,13 +74,25 @@
 }
 
 void
-Nlsrc::getStatus()
+Nlsrc::getStatus(const std::string& command)
 {
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
-  m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
-
+  if (command == "lsdb") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printLsdb, this));
+  }
+  else if (command == "routing") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printRT, this));
+  }
+  else if(command == "status") {
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchAdjacencyLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchCoordinateLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchNameLsas, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::fetchRtables, this));
+    m_fetchSteps.push_back(std::bind(&Nlsrc::printAll, this));
+  }
   runNextStep();
 }
 
@@ -97,12 +115,13 @@
     withdrawName();
     return true;
   }
-  else if (command == "status") {
+  else if ((command == "lsdb")|| (command == "routing")||(command == "status")) {
     if (nOptions != 0) {
       return false;
     }
+    commandString = command;
 
-    getStatus();
+    getStatus(command);
     return true;
   }
 
@@ -218,6 +237,15 @@
                                     std::bind(&Nlsrc::recordNameLsa, this, _1));
 }
 
+void
+Nlsrc::fetchRtables()
+{
+  fetchFromRt<nlsr::tlv::RoutingTable>(
+    [this] (const nlsr::tlv::RoutingTable& rts) {
+      recordRtable(rts);
+    });
+}
+
 template <class T>
 void
 Nlsrc::fetchFromLsdb(const ndn::Name::Component& datasetType,
@@ -238,8 +266,24 @@
 
 template <class T>
 void
+Nlsrc::fetchFromRt(const std::function<void(const T&)>& recordDataset)
+{
+  ndn::Name command = RT_PREFIX;
+
+  ndn::Interest interest(command);
+
+  ndn::util::SegmentFetcher::fetch(m_face,
+                                   interest,
+                                   m_validator,
+                                   std::bind(&Nlsrc::onFetchSuccess<T>,
+                                             this, _1, recordDataset),
+                                   std::bind(&Nlsrc::onTimeout, this, _1, _2));
+}
+
+template <class T>
+void
 Nlsrc::onFetchSuccess(const ndn::ConstBufferPtr& data,
-                      const std::function<void(const T&)>& recordLsa)
+                      const std::function<void(const T&)>& recordDataset)
 {
   ndn::Block block;
   size_t offset = 0;
@@ -255,8 +299,8 @@
 
     offset += block.size();
 
-    T lsa(block);
-    recordLsa(lsa);
+    T data(block);
+    recordDataset(data);
   }
 
   runNextStep();
@@ -278,10 +322,19 @@
   return os.str();
 }
 
+std::string
+Nlsrc::getDesString(const nlsr::tlv::Destination& des)
+{
+  std::ostringstream os;
+  os << "    " << des;
+
+  return os.str();
+}
+
 void
 Nlsrc::recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    AdjacencyLsa:" << std::endl;
@@ -298,7 +351,7 @@
 void
 Nlsrc::recordCoordinateLsa(const nlsr::tlv::CoordinateLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    Coordinate LSA:" << std::endl;
@@ -317,7 +370,7 @@
 void
 Nlsrc::recordNameLsa(const nlsr::tlv::NameLsa& lsa)
 {
-  Router& router = getRouter(lsa.getLsaInfo());
+  Router& router = getRouterLsdb(lsa.getLsaInfo());
 
   std::ostringstream os;
   os << "    Name LSA:" << std::endl;
@@ -332,9 +385,25 @@
 }
 
 void
+Nlsrc::recordRtable(const nlsr::tlv::RoutingTable& rt)
+{
+  Router& router = getRouterRT(rt.getDestination());
+
+  std::ostringstream os;
+
+  os << getDesString(rt.getDestination()) << std::endl;
+
+  os << "    NextHopList: " <<std::endl;
+  for (const auto& nhs : rt.getNextHops()) {
+    os << "      " << nhs;
+  }
+
+  router.rtString = os.str();
+}
+
+void
 Nlsrc::printLsdb()
 {
-  std::cout << "NLSR Status" << std::endl;
   std::cout << "LSDB:" << std::endl;
 
   for (const auto& item : m_routers) {
@@ -357,8 +426,31 @@
   }
 }
 
+void
+Nlsrc::printRT()
+{
+  std::cout << "Routing Table Status:" << std::endl;
+
+  for (const auto& item : m_routers) {
+
+    const Router& router = item.second;
+
+    if (!router.rtString.empty()) {
+      std::cout << router.rtString << std::endl;
+    }
+  }
+}
+
+void
+Nlsrc::printAll()
+{
+  std::cout << "NLSR Status" << std::endl;
+  printLsdb();
+  printRT();
+}
+
 Nlsrc::Router&
-Nlsrc::getRouter(const nlsr::tlv::LsaInfo& info)
+Nlsrc::getRouterLsdb(const nlsr::tlv::LsaInfo& info)
 {
   const ndn::Name& originRouterName = info.getOriginRouter();
 
@@ -368,6 +460,17 @@
   return pair.first->second;
 }
 
+Nlsrc::Router&
+Nlsrc::getRouterRT(const nlsr::tlv::Destination& des)
+{
+  const ndn::Name& desName = des.getName();
+
+  const auto& pair =
+    m_routers.insert(std::make_pair(desName, Router()));
+
+  return pair.first->second;
+}
+
 } // namespace nlsrc
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/tools/nlsrc.hpp b/tools/nlsrc.hpp
index 3dd44d6..a5c6368 100644
--- a/tools/nlsrc.hpp
+++ b/tools/nlsrc.hpp
@@ -1,6 +1,6 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
 /**
- * Copyright (c) 2014-2017,  The University of Memphis,
+ * Copyright (c) 2014-2018,  The University of Memphis,
  *                           Regents of the University of California,
  *                           Arizona Board of Regents.
  *
@@ -22,6 +22,8 @@
 #include "tlv/adjacency-lsa.hpp"
 #include "tlv/coordinate-lsa.hpp"
 #include "tlv/name-lsa.hpp"
+#include "tlv/routing-table-status.hpp"
+
 
 #include <boost/noncopyable.hpp>
 #include <ndn-cxx/face.hpp>
@@ -47,7 +49,7 @@
   printUsage();
 
   void
-  getStatus();
+  getStatus(const std::string& command);
 
   bool
   dispatch(const std::string& cmd);
@@ -89,6 +91,12 @@
   fetchAdjacencyLsas();
 
   void
+  fetchRtables();
+
+  void
+  fetchHRRtables();
+
+  void
   fetchCoordinateLsas();
 
   void
@@ -101,6 +109,10 @@
 
   template <class T>
   void
+  fetchFromRt(const std::function<void(const T&)>& recordLsa);
+
+  template <class T>
+  void
   onFetchSuccess(const ndn::ConstBufferPtr& data,
                  const std::function<void(const T&)>& recordLsa);
 
@@ -111,6 +123,9 @@
   std::string
   getLsaInfoString(const nlsr::tlv::LsaInfo& info);
 
+  std::string
+  getDesString(const nlsr::tlv::Destination& des);
+
   void
   recordAdjacencyLsa(const nlsr::tlv::AdjacencyLsa& lsa);
 
@@ -121,8 +136,17 @@
   recordNameLsa(const nlsr::tlv::NameLsa& lsa);
 
   void
+  recordRtable(const nlsr::tlv::RoutingTable& rts);
+
+  void
   printLsdb();
 
+  void
+  printRT();
+
+  void
+  printAll();
+
 public:
   const char* programName;
 
@@ -136,10 +160,14 @@
     std::string adjacencyLsaString;
     std::string coordinateLsaString;
     std::string nameLsaString;
+    std::string rtString;
   };
 
   Router&
-  getRouter(const nlsr::tlv::LsaInfo& info);
+  getRouterLsdb(const nlsr::tlv::LsaInfo& info);
+
+  Router&
+  getRouterRT(const nlsr::tlv::Destination& des);
 
   typedef std::map<const ndn::Name, Router> RouterMap;
   RouterMap m_routers;
@@ -148,6 +176,7 @@
   ndn::KeyChain m_keyChain;
   ndn::Face& m_face;
   ndn::security::ValidatorNull m_validator;
+  std::string commandString;
 
   std::deque<std::function<void()>> m_fetchSteps;
 
@@ -155,6 +184,8 @@
   static const ndn::Name LSDB_PREFIX;
   static const ndn::Name NAME_UPDATE_PREFIX;
 
+  static const ndn::Name RT_PREFIX;
+
   static const uint32_t ERROR_CODE_TIMEOUT;
   static const uint32_t RESPONSE_CODE_SUCCESS;
 };