publisher: implement routing table dataset publisher

refs: #3631, #3634

Change-Id: I7e961fdd0857690bee65d2bdfa4cf3de90ccac06
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