rib: simplify Route class
Route::expires is changed to an optional, with nullopt representing
"never expires". This avoids an integer overflow.
RouteFlags accessors are now provided by ndn::nfd::RouteFlagsTraits.
Stream insertion operator is improved.
refs #3502
Change-Id: Ia912eab771fb00020385bf84d486955feae6aafa
diff --git a/rib/fib-updater.cpp b/rib/fib-updater.cpp
index a430c68..bce3a5d 100644
--- a/rib/fib-updater.cpp
+++ b/rib/fib-updater.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -71,9 +71,8 @@
NFD_LOG_DEBUG("Computing updates for batch with faceID: " << batch.getFaceId());
// Compute updates and add to m_fibUpdates
- for (const RibUpdate& update : batch)
- {
- switch(update.getAction()) {
+ for (const RibUpdate& update : batch) {
+ switch (update.getAction()) {
case RibUpdate::REGISTER:
computeUpdatesForRegistration(update);
break;
@@ -87,8 +86,8 @@
// since they will be rejected by the FIB
m_updatesForBatchFaceId.clear();
break;
- }
}
+ }
}
void
@@ -108,7 +107,7 @@
// Route will be new
if (existingRoute == entry->end()) {
// Will the new route change the namespace's capture flag?
- bool willCaptureBeTurnedOn = (entry->hasCapture() == false && route.isCapture());
+ bool willCaptureBeTurnedOn = (entry->hasCapture() == false && route.isRibCapture());
createFibUpdatesForNewRoute(*entry, route, willCaptureBeTurnedOn);
}
@@ -383,11 +382,11 @@
addFibUpdate(FibUpdate::createAddUpdate(name, route.faceId, route.cost));
// No flags are set
- if (!route.isChildInherit() && !route.isCapture()) {
+ if (!route.isChildInherit() && !route.isRibCapture()) {
// Add ancestor routes to self
addInheritedRoutes(name, m_rib.getAncestorRoutes(name), route);
}
- else if (route.isChildInherit() && route.isCapture()) {
+ else if (route.isChildInherit() && route.isRibCapture()) {
// Add route to children
Rib::RouteSet routesToAdd;
routesToAdd.insert(route);
@@ -416,7 +415,7 @@
// Add ancestor routes to children
modifyChildrensInheritedRoutes(children, ancestorRoutes, Rib::RouteSet());
}
- else if (route.isCapture()) {
+ else if (route.isRibCapture()) {
// Remove routes blocked by capture
modifyChildrensInheritedRoutes(children, Rib::RouteSet(), m_rib.getAncestorRoutes(name));
}
@@ -540,7 +539,7 @@
}
// Capture was turned on
- if (!existingRoute.isCapture() && route.isCapture()) {
+ if (!existingRoute.isRibCapture() && route.isRibCapture()) {
Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
// Remove ancestor routes from self
@@ -549,7 +548,7 @@
// Remove ancestor routes from children
modifyChildrensInheritedRoutes(entry.getChildren(), Rib::RouteSet(), ancestorRoutes);
} // Capture was turned off
- else if (existingRoute.isCapture() && !route.isCapture()) {
+ else if (existingRoute.isRibCapture() && !route.isRibCapture()) {
Rib::RouteSet ancestorRoutes = m_rib.getAncestorRoutes(entry);
// Add ancestor routes to self
@@ -566,7 +565,7 @@
{
addFibUpdate(FibUpdate::createRemoveUpdate(entry.getName(), route.faceId));
- if (route.isChildInherit() && route.isCapture()) {
+ if (route.isChildInherit() && route.isRibCapture()) {
// Remove self from children
Rib::RouteSet routesToRemove;
routesToRemove.insert(route);
@@ -597,7 +596,7 @@
// Add ancestor routes to children
modifyChildrensInheritedRoutes(entry.getChildren(), routesToAdd, routesToRemove);
}
- else if (route.isCapture()) {
+ else if (route.isRibCapture()) {
// If capture is turned off for the route and another route is installed in the RibEntry,
// add ancestors to self
Rib::RouteSet routesToAdd;
diff --git a/rib/rib-entry.cpp b/rib/rib-entry.cpp
index a33e113..e26e6d6 100644
--- a/rib/rib-entry.cpp
+++ b/rib/rib-entry.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2016, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -249,10 +249,10 @@
operator<<(std::ostream& os, const RibEntry& entry)
{
os << "RibEntry {\n";
- os << "\tName: " << entry.getName() << "\n";
+ os << " Name: " << entry.getName() << "\n";
for (const Route& route : entry) {
- os << "\t" << route << "\n";
+ os << " " << route << "\n";
}
os << "}";
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index 46819bd..71a7cf3 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -33,13 +33,11 @@
#include <ndn-cxx/lp/tags.hpp>
#include <ndn-cxx/mgmt/nfd/control-command.hpp>
-#include <ndn-cxx/mgmt/nfd/control-response.hpp>
#include <ndn-cxx/mgmt/nfd/control-parameters.hpp>
+#include <ndn-cxx/mgmt/nfd/control-response.hpp>
#include <ndn-cxx/mgmt/nfd/face-status.hpp>
#include <ndn-cxx/mgmt/nfd/rib-entry.hpp>
-#include <boost/range/adaptor/transformed.hpp>
-
namespace nfd {
namespace rib {
@@ -219,14 +217,14 @@
scheduler::EventId eventId = scheduler::schedule(parameters.getExpirationPeriod(),
bind(&Rib::onRouteExpiration, &m_rib, parameters.getName(), route));
- NFD_LOG_TRACE("Scheduled unregistration at: " << route.expires <<
+ NFD_LOG_TRACE("Scheduled unregistration at: " << *route.expires <<
" with EventId: " << eventId);
// Set the NewEventId of this entry
route.setExpirationEvent(eventId);
}
else {
- route.expires = time::steady_clock::TimePoint::max();
+ route.expires = ndn::nullopt;
}
NFD_LOG_INFO("Adding route " << parameters.getName() << " nexthop=" << route.faceId
@@ -276,25 +274,23 @@
RibManager::listEntries(const Name& topPrefix, const Interest& interest,
ndn::mgmt::StatusDatasetContext& context)
{
- for (const auto& ribTableEntry : m_rib) {
- const auto& ribEntry = *ribTableEntry.second;
- const auto& routes = ribEntry.getRoutes() |
- boost::adaptors::transformed([] (const Route& route) {
- auto r = ndn::nfd::Route()
- .setFaceId(route.faceId)
- .setOrigin(route.origin)
- .setCost(route.cost)
- .setFlags(route.flags);
- if (route.expires < time::steady_clock::TimePoint::max()) {
- r.setExpirationPeriod(time::duration_cast<time::milliseconds>(
- route.expires - time::steady_clock::now()));
- }
- return r;
- });
- context.append(ndn::nfd::RibEntry()
- .setName(ribEntry.getName())
- .setRoutes(std::begin(routes), std::end(routes))
- .wireEncode());
+ auto now = time::steady_clock::now();
+ for (const auto& kv : m_rib) {
+ const RibEntry& entry = *kv.second;
+ ndn::nfd::RibEntry item;
+ item.setName(entry.getName());
+ for (const Route& route : entry.getRoutes()) {
+ ndn::nfd::Route r;
+ r.setFaceId(route.faceId);
+ r.setOrigin(route.origin);
+ r.setCost(route.cost);
+ r.setFlags(route.flags);
+ if (route.expires) {
+ r.setExpirationPeriod(time::duration_cast<time::milliseconds>(*route.expires - now));
+ }
+ item.addRoute(r);
+ }
+ context.append(item.wireEncode());
}
context.end();
}
@@ -409,7 +405,7 @@
Route route;
route.faceId = result.getFaceId();
route.origin = ndn::nfd::ROUTE_ORIGIN_APP;
- route.expires = time::steady_clock::TimePoint::max();
+ route.expires = ndn::nullopt;
route.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
m_rib.insert(prefix, route);
diff --git a/rib/route.cpp b/rib/route.cpp
index 7ee9353..08e469b 100644
--- a/rib/route.cpp
+++ b/rib/route.cpp
@@ -1,6 +1,6 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/**
- * Copyright (c) 2014-2015, Regents of the University of California,
+ * Copyright (c) 2014-2017, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -24,18 +24,27 @@
*/
#include "route.hpp"
+#include <ndn-cxx/util/string-helper.hpp>
namespace nfd {
namespace rib {
-bool
-Route::operator==(const Route& other) const
+Route::Route()
+ : faceId(0)
+ , origin(ndn::nfd::ROUTE_ORIGIN_APP)
+ , cost(0)
+ , flags(ndn::nfd::ROUTE_FLAGS_NONE)
{
- return (this->faceId == other.faceId &&
- this->origin == other.origin &&
- this->flags == other.flags &&
- this->cost == other.cost &&
- this->expires == other.expires);
+}
+
+bool
+operator==(const Route& lhs, const Route& rhs)
+{
+ return lhs.faceId == rhs.faceId &&
+ lhs.origin == rhs.origin &&
+ lhs.flags == rhs.flags &&
+ lhs.cost == rhs.cost &&
+ lhs.expires == rhs.expires;
}
std::ostream&
@@ -45,9 +54,9 @@
<< "faceid: " << route.faceId
<< ", origin: " << route.origin
<< ", cost: " << route.cost
- << ", flags: " << route.flags;
- if (route.expires != time::steady_clock::TimePoint::max()) {
- os << ", expires in: " << (route.expires - time::steady_clock::now());
+ << ", flags: " << ndn::AsHex{route.flags};
+ if (route.expires) {
+ os << ", expires in: " << time::duration_cast<time::milliseconds>(*route.expires - time::steady_clock::now());
}
else {
os << ", never expires";
diff --git a/rib/route.hpp b/rib/route.hpp
index f739741..2dfeabb 100644
--- a/rib/route.hpp
+++ b/rib/route.hpp
@@ -27,30 +27,20 @@
#define NFD_RIB_ROUTE_HPP
#include "core/scheduler.hpp"
-
#include <ndn-cxx/encoding/nfd-constants.hpp>
+#include <ndn-cxx/mgmt/nfd/route-flags-traits.hpp>
+#include <type_traits>
namespace nfd {
namespace rib {
/** \brief represents a route for a name prefix
*/
-class Route
+class Route : public ndn::nfd::RouteFlagsTraits<Route>
{
public:
- Route()
- : faceId(0)
- , origin(ndn::nfd::ROUTE_ORIGIN_APP)
- , flags(0)
- , cost(0)
- , expires(time::steady_clock::TimePoint::min())
- {
- }
+ Route();
- bool
- operator==(const Route& other) const;
-
-public:
void
setExpirationEvent(const scheduler::EventId eid)
{
@@ -63,29 +53,32 @@
return m_expirationEvent;
}
- bool
- isChildInherit() const
+ std::underlying_type<ndn::nfd::RouteFlags>::type
+ getFlags() const
{
- return flags & ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
- }
-
- bool
- isCapture() const
- {
- return flags & ndn::nfd::ROUTE_FLAG_CAPTURE;
+ return flags;
}
public:
uint64_t faceId;
ndn::nfd::RouteOrigin origin;
- uint64_t flags;
uint64_t cost;
- time::steady_clock::TimePoint expires;
+ std::underlying_type<ndn::nfd::RouteFlags>::type flags;
+ ndn::optional<time::steady_clock::TimePoint> expires;
private:
scheduler::EventId m_expirationEvent;
};
+bool
+operator==(const Route& lhs, const Route& rhs);
+
+inline bool
+operator!=(const Route& lhs, const Route& rhs)
+{
+ return !(lhs == rhs);
+}
+
inline bool
compareFaceIdAndOrigin(const Route& lhs, const Route& rhs)
{
diff --git a/tests/rib/fib-updates-common.hpp b/tests/rib/fib-updates-common.hpp
index 59505bc..925ca81 100644
--- a/tests/rib/fib-updates-common.hpp
+++ b/tests/rib/fib-updates-common.hpp
@@ -72,7 +72,7 @@
void
insertRoute(const Name& name, uint64_t faceId,
std::underlying_type<ndn::nfd::RouteOrigin>::type origin,
- uint64_t cost, uint64_t flags)
+ uint64_t cost, std::underlying_type<ndn::nfd::RouteFlags>::type flags)
{
Route route = createRoute(faceId, origin, cost, flags);
diff --git a/tests/rib/rib-manager.t.cpp b/tests/rib/rib-manager.t.cpp
index 117b264..42e8c93 100644
--- a/tests/rib/rib-manager.t.cpp
+++ b/tests/rib/rib-manager.t.cpp
@@ -434,7 +434,7 @@
Route route;
route.faceId = ++faceId;
route.cost = route.faceId * 10;
- route.expires = time::steady_clock::TimePoint::max();
+ route.expires = ndn::nullopt;
return route;
};
diff --git a/tests/rib/rib-test-common.hpp b/tests/rib/rib-test-common.hpp
index 3a09d4b..8cddafe 100644
--- a/tests/rib/rib-test-common.hpp
+++ b/tests/rib/rib-test-common.hpp
@@ -36,7 +36,7 @@
createRoute(uint64_t faceId,
std::underlying_type<ndn::nfd::RouteOrigin>::type origin,
uint64_t cost = 0,
- uint64_t flags = 0)
+ std::underlying_type<ndn::nfd::RouteFlags>::type flags = ndn::nfd::ROUTE_FLAGS_NONE)
{
Route temp;
temp.faceId = faceId;
diff --git a/tests/rib/rib.t.cpp b/tests/rib/rib.t.cpp
index d856f94..e572a72 100644
--- a/tests/rib/rib.t.cpp
+++ b/tests/rib/rib.t.cpp
@@ -291,31 +291,31 @@
Route root = createRoute(1, 20);
Name name1("/");
- root.expires = time::steady_clock::TimePoint::max();
+ root.expires = ndn::nullopt;
rib.insert(name1, root);
Route route1 = createRoute(2, 20);
Name name2("/hello");
- route1.expires = time::steady_clock::TimePoint::max();
+ route1.expires = ndn::nullopt;
rib.insert(name2, route1);
Route route2 = createRoute(3, 20);
Name name3("/hello/world");
- route2.expires = time::steady_clock::TimePoint::max();
+ route2.expires = ndn::nullopt;
rib.insert(name3, route2);
const std::string ribStr = std::string(R"TEXT(
RibEntry {
- Name: /
- Route(faceid: 1, origin: 20, cost: 0, flags: 0, never expires)
+ Name: /
+ Route(faceid: 1, origin: 20, cost: 0, flags: 0x0, never expires)
}
RibEntry {
- Name: /hello
- Route(faceid: 2, origin: 20, cost: 0, flags: 0, never expires)
+ Name: /hello
+ Route(faceid: 2, origin: 20, cost: 0, flags: 0x0, never expires)
}
RibEntry {
- Name: /hello/world
- Route(faceid: 3, origin: 20, cost: 0, flags: 0, never expires)
+ Name: /hello/world
+ Route(faceid: 3, origin: 20, cost: 0, flags: 0x0, never expires)
}
)TEXT").substr(1);
diff --git a/tests/rib/route.t.cpp b/tests/rib/route.t.cpp
new file mode 100644
index 0000000..d7b70eb
--- /dev/null
+++ b/tests/rib/route.t.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/**
+ * Copyright (c) 2014-2017, Regents of the University of California,
+ * Arizona Board of Regents,
+ * Colorado State University,
+ * University Pierre & Marie Curie, Sorbonne University,
+ * Washington University in St. Louis,
+ * Beijing Institute of Technology,
+ * The University of Memphis.
+ *
+ * This file is part of NFD (Named Data Networking Forwarding Daemon).
+ * See AUTHORS.md for complete list of NFD authors and contributors.
+ *
+ * NFD 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.
+ *
+ * NFD 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
+ * NFD, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "rib/route.hpp"
+#include "tests/test-common.hpp"
+
+namespace nfd {
+namespace rib {
+namespace tests {
+
+using namespace nfd::tests;
+
+BOOST_FIXTURE_TEST_SUITE(TestRoute, BaseFixture)
+
+BOOST_AUTO_TEST_CASE(Equality)
+{
+ Route a;
+ Route b;
+ BOOST_CHECK_EQUAL(a, b);
+
+ a.faceId = b.faceId = 15404;
+ a.origin = b.origin = ndn::nfd::ROUTE_ORIGIN_NLSR;
+ a.flags = b.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
+ a.cost = b.cost = 28826;
+ a.expires = b.expires = time::steady_clock::now() + time::milliseconds(26782232);
+ BOOST_CHECK_EQUAL(a, b);
+
+ b.faceId = 18559;
+ BOOST_CHECK_NE(a, b);
+ a.faceId = 18559;
+
+ b.origin = ndn::nfd::ROUTE_ORIGIN_CLIENT;
+ BOOST_CHECK_NE(a, b);
+ a.origin = ndn::nfd::ROUTE_ORIGIN_CLIENT;
+
+ b.flags = ndn::nfd::ROUTE_FLAG_CAPTURE;
+ BOOST_CHECK_NE(a, b);
+ a.flags = ndn::nfd::ROUTE_FLAG_CAPTURE;
+
+ b.cost = 103;
+ BOOST_CHECK_NE(a, b);
+ a.cost = 103;
+
+ b.expires = ndn::nullopt;
+ BOOST_CHECK_NE(a, b);
+ a.expires = ndn::nullopt;
+
+ BOOST_CHECK_EQUAL(a, b);
+}
+
+BOOST_FIXTURE_TEST_CASE(Output, UnitTestTimeFixture)
+{
+ Route r;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(r),
+ "Route(faceid: 0, origin: app, cost: 0, flags: 0x0, never expires)");
+
+ r.faceId = 4980;
+ r.origin = ndn::nfd::ROUTE_ORIGIN_STATIC;
+ r.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
+ r.cost = 2312;
+ r.expires = time::steady_clock::now() + time::milliseconds(791214234);
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(r),
+ "Route(faceid: 4980, origin: static, cost: 2312, flags: 0x1, expires in: 791214234 milliseconds)");
+
+ r.expires = ndn::nullopt;
+ BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(r),
+ "Route(faceid: 4980, origin: static, cost: 2312, flags: 0x1, never expires)");
+}
+
+BOOST_AUTO_TEST_SUITE_END() // TestRoute
+
+} // namespace tests
+} // namespace rib
+} // namespace nfd