rib: put PrefixAnnouncement in Route and RibEntry
refs #4650
Change-Id: I03a846cd6e013d52f080bd7b092cd392b0284f88
diff --git a/rib/rib-entry.cpp b/rib/rib-entry.cpp
index ff646fa..d59338d 100644
--- a/rib/rib-entry.cpp
+++ b/rib/rib-entry.cpp
@@ -238,6 +238,39 @@
return candidate;
}
+ndn::PrefixAnnouncement
+RibEntry::getPrefixAnnouncement(time::milliseconds minExpiration,
+ time::milliseconds maxExpiration) const
+{
+ const Route* bestAnnRoute = nullptr;
+ auto entryExpiry = time::steady_clock::TimePoint::min();
+
+ for (const Route& route : *this) {
+ if (route.expires) {
+ entryExpiry = std::max(entryExpiry, *route.expires);
+ if (route.announcement) {
+ if (bestAnnRoute == nullptr || *route.expires > *bestAnnRoute->expires) {
+ bestAnnRoute = &route;
+ }
+ }
+ }
+ else {
+ entryExpiry = time::steady_clock::TimePoint::max();
+ }
+ }
+
+ if (bestAnnRoute != nullptr) {
+ return *bestAnnRoute->announcement;
+ }
+
+ ndn::PrefixAnnouncement ann;
+ ann.setAnnouncedName(m_name);
+ ann.setExpiration(ndn::clamp(
+ time::duration_cast<time::milliseconds>(entryExpiry - time::steady_clock::now()),
+ minExpiration, maxExpiration));
+ return ann;
+}
+
std::ostream&
operator<<(std::ostream& os, const RibEntry& entry)
{
diff --git a/rib/rib-entry.hpp b/rib/rib-entry.hpp
index 161ebd4..60da09b 100644
--- a/rib/rib-entry.hpp
+++ b/rib/rib-entry.hpp
@@ -165,6 +165,22 @@
const Route*
getRouteWithLowestCostAndChildInheritByFaceId(uint64_t faceId) const;
+ /** \brief Retrieve a prefix announcement suitable for readvertising this route.
+ *
+ * If one or more routes in this RIB entry contains a prefix announcement, this method returns
+ * the announcement from the route that expires last.
+ *
+ * If this RIB entry does not have a route containing a prefix announcement, this method creates
+ * a new announcement. Its expiration period reflects the remaining lifetime of this RIB entry,
+ * confined within [\p minExpiration, \p maxExpiration] range. The caller is expected to sign
+ * this announcement.
+ *
+ * \warning (minExpiration > maxExpiration) triggers undefined behavior.
+ */
+ ndn::PrefixAnnouncement
+ getPrefixAnnouncement(time::milliseconds minExpiration = 15_s,
+ time::milliseconds maxExpiration = 1_h) const;
+
const_iterator
begin() const;
diff --git a/rib/rib.cpp b/rib/rib.cpp
index 542a582..5385cf1 100644
--- a/rib/rib.cpp
+++ b/rib/rib.cpp
@@ -113,12 +113,10 @@
scheduler::cancel(entryIt->getExpirationEvent());
}
+ *entryIt = route;
+
// No checks are required here as the iterator needs to be updated in all cases.
entryIt->setExpirationEvent(route.getExpirationEvent());
-
- entryIt->flags = route.flags;
- entryIt->cost = route.cost;
- entryIt->expires = route.expires;
}
}
else {
diff --git a/rib/route.cpp b/rib/route.cpp
index 08e469b..04999bb 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-2017, Regents of the University of California,
+/*
+ * Copyright (c) 2014-2018, Regents of the University of California,
* Arizona Board of Regents,
* Colorado State University,
* University Pierre & Marie Curie, Sorbonne University,
@@ -29,11 +29,33 @@
namespace nfd {
namespace rib {
-Route::Route()
- : faceId(0)
- , origin(ndn::nfd::ROUTE_ORIGIN_APP)
- , cost(0)
- , flags(ndn::nfd::ROUTE_FLAGS_NONE)
+const uint64_t PA_ROUTE_COST = 2048; ///< cost of route created by prefix announcement
+
+static time::steady_clock::TimePoint
+computeExpiration(const ndn::PrefixAnnouncement& ann)
+{
+ time::steady_clock::Duration validityEnd = time::steady_clock::Duration::max();
+ if (ann.getValidityPeriod()) {
+ auto now = time::system_clock::now();
+ if (!ann.getValidityPeriod()->isValid(now)) {
+ validityEnd = time::steady_clock::Duration::zero();
+ }
+ else {
+ validityEnd = ann.getValidityPeriod()->getPeriod().second - now;
+ }
+ }
+ return time::steady_clock::now() +
+ std::min(validityEnd, time::duration_cast<time::steady_clock::Duration>(ann.getExpiration()));
+}
+
+Route::Route(const ndn::PrefixAnnouncement& ann, uint64_t faceId)
+ : faceId(faceId)
+ , origin(ndn::nfd::ROUTE_ORIGIN_PREFIXANN)
+ , cost(PA_ROUTE_COST)
+ , flags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT)
+ , expires(computeExpiration(ann))
+ , announcement(ann)
+ , annExpires(*expires)
{
}
@@ -44,7 +66,8 @@
lhs.origin == rhs.origin &&
lhs.flags == rhs.flags &&
lhs.cost == rhs.cost &&
- lhs.expires == rhs.expires;
+ lhs.expires == rhs.expires &&
+ lhs.announcement == rhs.announcement;
}
std::ostream&
@@ -61,7 +84,10 @@
else {
os << ", never expires";
}
- os << ")";
+ if (route.announcement) {
+ os << ", announcement: (" << *route.announcement << ')';
+ }
+ os << ')';
return os;
}
diff --git a/rib/route.hpp b/rib/route.hpp
index 5ad4d79..8106406 100644
--- a/rib/route.hpp
+++ b/rib/route.hpp
@@ -30,6 +30,7 @@
#include <ndn-cxx/encoding/nfd-constants.hpp>
#include <ndn-cxx/mgmt/nfd/route-flags-traits.hpp>
+#include <ndn-cxx/prefix-announcement.hpp>
#include <type_traits>
@@ -41,7 +42,15 @@
class Route : public ndn::nfd::RouteFlagsTraits<Route>
{
public:
- Route();
+ /** \brief default constructor
+ */
+ Route() = default;
+
+ /** \brief construct from a prefix announcement
+ * \param ann a prefix announcement that has passed verification
+ * \param faceId the face on which \p ann arrived
+ */
+ Route(const ndn::PrefixAnnouncement& ann, uint64_t faceId);
void
setExpirationEvent(const scheduler::EventId eid)
@@ -62,12 +71,28 @@
}
public:
- uint64_t faceId;
- ndn::nfd::RouteOrigin origin;
- uint64_t cost;
- std::underlying_type<ndn::nfd::RouteFlags>::type flags;
+ uint64_t faceId = 0;
+ ndn::nfd::RouteOrigin origin = ndn::nfd::ROUTE_ORIGIN_APP;
+ uint64_t cost = 0;
+ std::underlying_type<ndn::nfd::RouteFlags>::type flags = ndn::nfd::ROUTE_FLAGS_NONE;
optional<time::steady_clock::TimePoint> expires;
+ /** \brief The prefix announcement that caused the creation of this route.
+ *
+ * This is nullopt if this route is not created by a prefix announcement.
+ */
+ optional<ndn::PrefixAnnouncement> announcement;
+
+ /** \brief Expiration time of the prefix announcement.
+ *
+ * Valid only if announcement is not nullopt.
+ *
+ * If this field is before or equal the current time, it indicates the prefix announcement is
+ * not yet valid or has expired. In this case, the exact value of this field does not matter.
+ * If this field is after the current time, it indicates when the prefix announcement expires.
+ */
+ time::steady_clock::TimePoint annExpires;
+
private:
scheduler::EventId m_expirationEvent;
};