rib: Switch RibManager to use NFD RIB Management protocol

Change-Id: I725529a96b5ad4318e0e0a8c2bd61b84ae439a32
Refs: #1490
diff --git a/daemon/mgmt/fib-manager.cpp b/daemon/mgmt/fib-manager.cpp
index 26c3c2e..5afa492 100644
--- a/daemon/mgmt/fib-manager.cpp
+++ b/daemon/mgmt/fib-manager.cpp
@@ -137,8 +137,8 @@
   const Name::Component& verb = command[COMMAND_PREFIX.size()];
   const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
 
-  SignedVerbDispatchTable::const_iterator signedVerbProcessor = m_signedVerbDispatch.find (verb);
-  if (signedVerbProcessor != m_signedVerbDispatch.end())
+  SignedVerbDispatchTable::const_iterator verbProcessor = m_signedVerbDispatch.find(verb);
+  if (verbProcessor != m_signedVerbDispatch.end())
     {
       ControlParameters parameters;
       if (!extractParameters(parameterComponent, parameters) || !parameters.hasFaceId())
@@ -155,7 +155,7 @@
 
       NFD_LOG_DEBUG("command result: processing verb: " << verb);
       ControlResponse response;
-      (signedVerbProcessor->second)(this, parameters, response);
+      (verbProcessor->second)(this, parameters, response);
       sendResponse(command, response);
     }
   else
diff --git a/nfd.conf.sample.in b/nfd.conf.sample.in
index b0288e4..8c48743 100644
--- a/nfd.conf.sample.in
+++ b/nfd.conf.sample.in
@@ -193,7 +193,7 @@
     filter
     {
       type name                               ; condition on interest name (w/o signature)
-      regex ^[<localhop><localhost>]<nrd>[<register><unregister>]<>{3}$
+      regex ^[<localhop><localhost>]<nfd><rib>[<register><unregister>]<>{3}$
     }
     checker
     {
diff --git a/rib/rib-manager.cpp b/rib/rib-manager.cpp
index afcd1b3..3594a71 100644
--- a/rib/rib-manager.cpp
+++ b/rib/rib-manager.cpp
@@ -32,8 +32,8 @@
 
 NFD_LOG_INIT("RibManager");
 
-const Name RibManager::COMMAND_PREFIX = "/localhost/nrd";
-const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nrd";
+const Name RibManager::COMMAND_PREFIX = "/localhost/nfd/rib";
+const Name RibManager::REMOTE_COMMAND_PREFIX = "/localhop/nfd/rib";
 
 const size_t RibManager::COMMAND_UNSIGNED_NCOMPS =
   RibManager::COMMAND_PREFIX.size() +
@@ -48,12 +48,12 @@
   {
     VerbAndProcessor(
                      Name::Component("register"),
-                     &RibManager::insertEntry
+                     &RibManager::registerEntry
                      ),
 
     VerbAndProcessor(
                      Name::Component("unregister"),
-                     &RibManager::deleteEntry
+                     &RibManager::unregisterEntry
                      ),
   };
 
@@ -79,14 +79,14 @@
   //check whether the components of localhop and localhost prefixes are same
   BOOST_ASSERT(COMMAND_PREFIX.size() == REMOTE_COMMAND_PREFIX.size());
 
-  NFD_LOG_INFO("Setting interest filter on: " << COMMAND_PREFIX.toUri());
+  NFD_LOG_INFO("Setting interest filter on: " << COMMAND_PREFIX);
   m_face.setController(m_nfdController);
-  m_face.setInterestFilter(COMMAND_PREFIX.toUri(),
+  m_face.setInterestFilter(COMMAND_PREFIX,
                            bind(&RibManager::onRibRequest, this, _2),
                            bind(&RibManager::setInterestFilterFailed, this, _1, _2));
 
-  NFD_LOG_INFO("Setting interest filter on: " << REMOTE_COMMAND_PREFIX.toUri());
-  m_face.setInterestFilter(REMOTE_COMMAND_PREFIX.toUri(),
+  NFD_LOG_INFO("Setting interest filter on: " << REMOTE_COMMAND_PREFIX);
+  m_face.setInterestFilter(REMOTE_COMMAND_PREFIX,
                            bind(&RibManager::onRibRequest, this, _2),
                            bind(&RibManager::setInterestFilterFailed, this, _1, _2));
 
@@ -145,37 +145,38 @@
 RibManager::onRibRequest(const Interest& request)
 {
   m_validator.validate(request,
-                       bind(&RibManager::onRibRequestValidated, this, _1),
-                       bind(&RibManager::onRibRequestValidationFailed, this, _1, _2));
+                       bind(&RibManager::onCommandValidated, this, _1),
+                       bind(&RibManager::onCommandValidationFailed, this, _1, _2));
 }
 
 void
-RibManager::onRibRequestValidated(const shared_ptr<const Interest>& request)
+RibManager::onCommandValidated(const shared_ptr<const Interest>& request)
 {
-  const Name& command = request->getName();
-
-  //REMOTE_COMMAND_PREFIX number of componenets are same as
+  // REMOTE_COMMAND_PREFIX number of componenets are same as
   // NRD_COMMAND_PREFIX's so no extra checks are required.
-  const Name::Component& verb = command.get(COMMAND_PREFIX.size());
-  VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
 
+  const Name& command = request->getName();
+  const Name::Component& verb = command[COMMAND_PREFIX.size()];
+  const Name::Component& parameterComponent = command[COMMAND_PREFIX.size() + 1];
+
+  VerbDispatchTable::const_iterator verbProcessor = m_verbDispatch.find(verb);
   if (verbProcessor != m_verbDispatch.end())
     {
-      NFD_LOG_TRACE("Processing '" << verb << "' verb");
-
-      PrefixRegOptions options;
-      if (!extractOptions(*request, options))
+      ControlParameters parameters;
+      if (!extractParameters(parameterComponent, parameters))
         {
-          NFD_LOG_DEBUG("Error while extracting options, returning malformed command");
+          NFD_LOG_DEBUG("command result: malformed verb: " << verb);
           sendResponse(command, 400, "Malformed command");
           return;
         }
 
-      NFD_LOG_DEBUG("Received options (name, faceid, cost): " << options.getName()
-                    << ", " << options.getFaceId() << ", "  << options.getCost());
+      if (!parameters.hasFaceId() || parameters.getFaceId() == 0)
+        {
+          parameters.setFaceId(request->getIncomingFaceId());
+        }
 
-      ControlResponse response;
-      (verbProcessor->second)(this, *request, options);
+      NFD_LOG_DEBUG("command result: processing verb: " << verb);
+      (verbProcessor->second)(this, request, parameters);
     }
   else
     {
@@ -185,44 +186,119 @@
 }
 
 void
-RibManager::onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
-                                         const std::string& failureInfo)
+RibManager::registerEntry(const shared_ptr<const Interest>& request,
+                          ControlParameters& parameters)
+{
+  ndn::nfd::RibRegisterCommand command;
+
+  if (!validateParameters(command, parameters))
+    {
+      NFD_LOG_DEBUG("register result: FAIL reason: malformed");
+      sendResponse(request->getName(), 400, "Malformed command");
+      return;
+    }
+
+  RibEntry ribEntry;
+  ribEntry.name = parameters.getName();
+  ribEntry.faceId = parameters.getFaceId();
+  ribEntry.origin = parameters.getOrigin();
+  ribEntry.cost = parameters.getCost();
+  ribEntry.flags = parameters.getFlags();
+  ribEntry.expires = time::steady_clock::now() + parameters.getExpirationPeriod();
+
+  NFD_LOG_TRACE("register prefix: " << ribEntry);
+
+  // For right now, just pass the options to fib as it is,
+  // without processing flags. Later options will be first added to
+  // Rib tree, then nrd will generate fib updates based on flags and then
+  // will add next hops one by one..
+  m_managedRib.insert(ribEntry);
+  m_nfdController->start<ndn::nfd::FibAddNextHopCommand>(
+    ControlParameters()
+      .setName(ribEntry.name)
+      .setFaceId(ribEntry.faceId)
+      .setCost(ribEntry.cost),
+    bind(&RibManager::onRegSuccess, this, request, parameters, ribEntry),
+    bind(&RibManager::onCommandError, this, _1, _2, request, ribEntry));
+}
+
+void
+RibManager::unregisterEntry(const shared_ptr<const Interest>& request,
+                            ControlParameters& parameters)
+{
+  ndn::nfd::RibRegisterCommand command;
+
+  if (!validateParameters(command, parameters))
+    {
+      NFD_LOG_DEBUG("register result: FAIL reason: malformed");
+      sendResponse(request->getName(), 400, "Malformed command");
+      return;
+    }
+
+  RibEntry ribEntry;
+  ribEntry.name = parameters.getName();
+  ribEntry.faceId = parameters.getFaceId();
+  ribEntry.origin = parameters.getOrigin();
+
+  NFD_LOG_TRACE("unregister prefix: " << ribEntry);
+
+  m_nfdController->start<ndn::nfd::FibRemoveNextHopCommand>(
+    ControlParameters()
+      .setName(ribEntry.name)
+      .setFaceId(ribEntry.faceId),
+    bind(&RibManager::onUnRegSuccess, this, request, parameters, ribEntry),
+    bind(&RibManager::onCommandError, this, _1, _2, request, ribEntry));
+}
+
+void
+RibManager::onCommandValidationFailed(const shared_ptr<const Interest>& request,
+                                      const std::string& failureInfo)
 {
   NFD_LOG_DEBUG("RibRequestValidationFailed: " << failureInfo);
   sendResponse(request->getName(), 403, failureInfo);
 }
 
-bool
-RibManager::extractOptions(const Interest& request,
-                           PrefixRegOptions& extractedOptions)
-{
-  // const Name& command = request.getName();
-  //REMOTE_COMMAND_PREFIX is same in size of NRD_COMMAND_PREFIX
-  //so no extra processing is required.
-  const size_t optionCompIndex = COMMAND_PREFIX.size() + 1;
 
+bool
+RibManager::extractParameters(const Name::Component& parameterComponent,
+                              ControlParameters& extractedParameters)
+{
   try
     {
-      Block rawOptions = request.getName()[optionCompIndex].blockFromValue();
-      extractedOptions.wireDecode(rawOptions);
+      Block rawParameters = parameterComponent.blockFromValue();
+      extractedParameters.wireDecode(rawParameters);
     }
   catch (const ndn::Tlv::Error& e)
     {
       return false;
     }
 
-  if (extractedOptions.getFaceId() == 0)
+  NFD_LOG_DEBUG("Parameters parsed OK");
+  return true;
+}
+
+bool
+RibManager::validateParameters(const ControlCommand& command,
+                               ControlParameters& parameters)
+{
+  try
     {
-      NFD_LOG_TRACE("IncomingFaceId: " << request.getIncomingFaceId());
-      extractedOptions.setFaceId(request.getIncomingFaceId());
+      command.validateRequest(parameters);
     }
+  catch (const ControlCommand::ArgumentError&)
+    {
+      return false;
+    }
+
+  command.applyDefaultsToRequest(parameters);
+
   return true;
 }
 
 void
 RibManager::onCommandError(uint32_t code, const std::string& error,
-                           const Interest& request,
-                           const PrefixRegOptions& options)
+                           const shared_ptr<const Interest>& request,
+                           const RibEntry& ribEntry)
 {
   NFD_LOG_ERROR("NFD returned an error: " << error << " (code: " << code << ")");
 
@@ -241,66 +317,42 @@
       response.setText(os.str());
     }
 
-  sendResponse(request.getName(), response);
-  m_managedRib.erase(options);
+  sendResponse(request->getName(), response);
+  m_managedRib.erase(ribEntry);
 }
 
 void
-RibManager::onUnRegSuccess(const Interest& request, const PrefixRegOptions& options)
+RibManager::onRegSuccess(const shared_ptr<const Interest>& request,
+                         const ControlParameters& parameters,
+                         const RibEntry& ribEntry)
 {
   ControlResponse response;
 
   response.setCode(200);
   response.setText("Success");
-  response.setBody(options.wireEncode());
+  response.setBody(parameters.wireEncode());
 
-  NFD_LOG_DEBUG("onUnRegSuccess: Name unregistered (" << options.getName()
-                << ", " << options.getFaceId() << ")");
+  NFD_LOG_TRACE("onRegSuccess: registered " << ribEntry);
 
-  sendResponse(request.getName(), response);
-  m_managedRib.erase(options);
+  sendResponse(request->getName(), response);
 }
 
+
 void
-RibManager::onRegSuccess(const Interest& request, const PrefixRegOptions& options)
+RibManager::onUnRegSuccess(const shared_ptr<const Interest>& request,
+                           const ControlParameters& parameters,
+                           const RibEntry& ribEntry)
 {
   ControlResponse response;
 
   response.setCode(200);
   response.setText("Success");
-  response.setBody(options.wireEncode());
+  response.setBody(parameters.wireEncode());
 
-  NFD_LOG_DEBUG("onRegSuccess: Name registered (" << options.getName() << ", "
-                << options.getFaceId() << ")");
-  sendResponse(request.getName(), response);
-}
+  NFD_LOG_TRACE("onUnRegSuccess: unregistered " << ribEntry);
 
-void
-RibManager::insertEntry(const Interest& request, const PrefixRegOptions& options)
-{
-  // For right now, just pass the options to fib as it is,
-  // without processing flags. Later options will be first added to
-  // Rib tree, then nrd will generate fib updates based on flags and then
-  // will add next hops one by one..
-  m_managedRib.insert(options);
-  m_nfdController->start<ndn::nfd::FibAddNextHopCommand>(
-    ControlParameters()
-      .setName(options.getName())
-      .setFaceId(options.getFaceId())
-      .setCost(options.getCost()),
-    bind(&RibManager::onRegSuccess, this, request, options),
-    bind(&RibManager::onCommandError, this, _1, _2, request, options));
-}
-
-void
-RibManager::deleteEntry(const Interest& request, const PrefixRegOptions& options)
-{
-  m_nfdController->start<ndn::nfd::FibRemoveNextHopCommand>(
-    ControlParameters()
-      .setName(options.getName())
-      .setFaceId(options.getFaceId()),
-    bind(&RibManager::onUnRegSuccess, this, request, options),
-    bind(&RibManager::onCommandError, this, _1, _2, request, options));
+  sendResponse(request->getName(), response);
+  m_managedRib.erase(ribEntry);
 }
 
 void
diff --git a/rib/rib-manager.hpp b/rib/rib-manager.hpp
index 44299e6..a8984b1 100644
--- a/rib/rib-manager.hpp
+++ b/rib/rib-manager.hpp
@@ -76,22 +76,35 @@
                const std::string& text);
 
   void
-  onRibRequestValidated(const shared_ptr<const Interest>& request);
+  registerEntry(const shared_ptr<const Interest>& request,
+                ControlParameters& parameters);
 
   void
-  onRibRequestValidationFailed(const shared_ptr<const Interest>& request,
-                               const std::string& failureInfo);
+  unregisterEntry(const shared_ptr<const Interest>& request,
+                  ControlParameters& parameters);
+
+  void
+  onCommandValidated(const shared_ptr<const Interest>& request);
+
+  void
+  onCommandValidationFailed(const shared_ptr<const Interest>& request,
+                            const std::string& failureInfo);
+
 
   void
   onCommandError(uint32_t code, const std::string& error,
-                 const ndn::Interest& interest,
-                 const PrefixRegOptions& options);
+                 const shared_ptr<const Interest>& request,
+                 const RibEntry& ribEntry);
 
   void
-  onRegSuccess(const ndn::Interest& interest, const PrefixRegOptions& options);
+  onRegSuccess(const shared_ptr<const Interest>& request,
+               const ControlParameters& parameters,
+               const RibEntry& ribEntry);
 
   void
-  onUnRegSuccess(const ndn::Interest& interest, const PrefixRegOptions& options);
+  onUnRegSuccess(const shared_ptr<const Interest>& request,
+                 const ControlParameters& parameters,
+                 const RibEntry& ribEntry);
 
   void
   onControlHeaderSuccess();
@@ -102,15 +115,13 @@
   void
   setInterestFilterFailed(const Name& name, const std::string& msg);
 
-  void
-  insertEntry(const Interest& request, const PrefixRegOptions& options);
-
-  void
-  deleteEntry(const Interest& request, const PrefixRegOptions& options);
+  static bool
+  extractParameters(const Name::Component& parameterComponent,
+                    ControlParameters& extractedParameters);
 
   bool
-  extractOptions(const Interest& request,
-                 PrefixRegOptions& extractedOptions);
+  validateParameters(const ControlCommand& command,
+                     ControlParameters& parameters);
 
   void
   onNotification(const FaceEventNotification& notification);
@@ -124,8 +135,8 @@
   FaceMonitor m_faceMonitor;
 
   typedef boost::function<void(RibManager*,
-                               const Interest&,
-                               const PrefixRegOptions&)> VerbProcessor;
+                               const shared_ptr<const Interest>& request,
+                               ControlParameters& parameters)> VerbProcessor;
 
   typedef std::map<name::Component, VerbProcessor> VerbDispatchTable;
 
diff --git a/rib/rib.cpp b/rib/rib.cpp
index 8ad5ec6..4dc4175 100644
--- a/rib/rib.cpp
+++ b/rib/rib.cpp
@@ -38,19 +38,19 @@
 }
 
 static inline bool
-compareNameFaceProtocol(const PrefixRegOptions& opt1, const PrefixRegOptions& opt2)
+compareNameFaceProtocol(const RibEntry& entry1, const RibEntry& entry2)
 {
-  return (opt1.getName() == opt2.getName() &&
-          opt1.getFaceId() == opt2.getFaceId() &&
-          opt1.getProtocol() == opt2.getProtocol());
+  return (entry1.name == entry2.name &&
+          entry1.faceId == entry2.faceId &&
+          entry1.origin == entry2.origin);
 }
 
 
 Rib::const_iterator
-Rib::find(const PrefixRegOptions& options) const
+Rib::find(const RibEntry& entry) const
 {
   RibTable::const_iterator it = std::find_if(m_rib.begin(), m_rib.end(),
-                                             bind(&compareNameFaceProtocol, _1, options));
+                                             bind(&compareNameFaceProtocol, _1, entry));
   if (it == m_rib.end())
     {
       return end();
@@ -61,30 +61,29 @@
 
 
 void
-Rib::insert(const PrefixRegOptions& options)
+Rib::insert(const RibEntry& entry)
 {
   RibTable::iterator it = std::find_if(m_rib.begin(), m_rib.end(),
-                                       bind(&compareNameFaceProtocol, _1, options));
+                                       bind(&compareNameFaceProtocol, _1, entry));
   if (it == m_rib.end())
     {
-      m_rib.push_front(options);
+      m_rib.push_front(entry);
     }
   else
     {
-      //entry exist, update other fields
-      it->setFlags(options.getFlags());
-      it->setCost(options.getCost());
-      it->setExpirationPeriod(options.getExpirationPeriod());
-      it->setProtocol(options.getProtocol());
+      // entry exist, update other fields
+      it->flags = entry.flags;
+      it->cost = entry.cost;
+      it->expires = entry.expires;
     }
 }
 
 
 void
-Rib::erase(const PrefixRegOptions& options)
+Rib::erase(const RibEntry& entry)
 {
   RibTable::iterator it = std::find_if(m_rib.begin(), m_rib.end(),
-                                       bind(&compareNameFaceProtocol, _1, options));
+                                       bind(&compareNameFaceProtocol, _1, entry));
   if (it != m_rib.end())
     {
       m_rib.erase(it);
@@ -94,16 +93,31 @@
 void
 Rib::erase(uint64_t faceId)
 {
-  //Keep it simple for now, with Trie this will be changed.
+  // Keep it simple for now, with Trie this will be changed.
   RibTable::iterator it = m_rib.begin();
   while (it != m_rib.end())
   {
-    if (it->getFaceId() == faceId)
+    if (it->faceId == faceId)
       it = m_rib.erase(it);
     else
       ++it;
   }
 }
 
+std::ostream&
+operator<<(std::ostream& os, const RibEntry& entry)
+{
+  os << "RibEntry("
+     << "name: " << entry.name
+     << " faceid: " << entry.faceId
+     << " origin: " << entry.origin
+     << " cost: " << entry.cost
+     << " flags: " << entry.flags
+     << " expires in: " << (entry.expires - time::steady_clock::now())
+     << ")";
+
+  return os;
+}
+
 } // namespace rib
 } // namespace nfd
diff --git a/rib/rib.hpp b/rib/rib.hpp
index 745a760..e2371eb 100644
--- a/rib/rib.hpp
+++ b/rib/rib.hpp
@@ -27,21 +27,38 @@
 #define NFD_RIB_RIB_HPP
 
 #include "common.hpp"
-
-#include <ndn-cpp-dev/management/nrd-prefix-reg-options.hpp>
+#include <ndn-cpp-dev/management/nfd-control-command.hpp>
 
 namespace nfd {
 namespace rib {
 
-using ndn::nrd::PrefixRegOptions;
-namespace tlv = ndn::tlv;
+class RibEntry
+{
+public:
+  RibEntry()
+    : faceId(0)
+    , origin(0)
+    , flags(0)
+    , cost(0)
+    , expires(time::steady_clock::TimePoint::min())
+  {
+  }
+
+public:
+  Name name;
+  uint64_t faceId;
+  uint64_t origin;
+  uint64_t flags;
+  uint64_t cost;
+  time::steady_clock::TimePoint expires;
+};
 
 /** \brief represents the RIB
  */
-class Rib
+class Rib : noncopyable
 {
 public:
-  typedef std::list<PrefixRegOptions> RibTable;
+  typedef std::list<RibEntry> RibTable;
   typedef RibTable::const_iterator const_iterator;
 
   Rib();
@@ -49,13 +66,13 @@
   ~Rib();
 
   const_iterator
-  find(const PrefixRegOptions& options) const;
+  find(const RibEntry& entry) const;
 
   void
-  insert(const PrefixRegOptions& options);
+  insert(const RibEntry& entry);
 
   void
-  erase(const PrefixRegOptions& options);
+  erase(const RibEntry& entry);
 
   void
   erase(uint64_t faceId);
@@ -102,6 +119,9 @@
   return m_rib.empty();
 }
 
+std::ostream&
+operator<<(std::ostream& os, const RibEntry& entry);
+
 } // namespace rib
 } // namespace nfd
 
diff --git a/tests/rib/rib.cpp b/tests/rib/rib.cpp
index fd5777b..a8a0110 100644
--- a/tests/rib/rib.cpp
+++ b/tests/rib/rib.cpp
@@ -37,46 +37,59 @@
 {
   rib::Rib rib;
 
-  PrefixRegOptions options1;
-  options1.setName("/hello/world");
-  options1.setFlags(tlv::nrd::NDN_FORW_CHILD_INHERIT | tlv::nrd::NDN_FORW_CAPTURE);
-  options1.setCost(10);
-  options1.setExpirationPeriod(time::milliseconds(1500));
-  options1.setFaceId(1);
+  RibEntry entry1;
+  entry1.name = "/hello/world";
+  entry1.faceId = 1;
+  entry1.origin = 20;
+  entry1.cost = 10;
+  entry1.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT | ndn::nfd::ROUTE_FLAG_CAPTURE;
+  entry1.expires = time::steady_clock::now() + time::milliseconds(1500);
 
-  rib.insert(options1);
+  rib.insert(entry1);
   BOOST_CHECK_EQUAL(rib.size(), 1);
 
-  PrefixRegOptions options2;
-  options2.setName("/hello/world");
-  options2.setFlags(tlv::nrd::NDN_FORW_CHILD_INHERIT);
-  options2.setExpirationPeriod(time::seconds(0));
-  options2.setFaceId(1);
-  options2.setCost(100);
-
-  rib.insert(options2);
+  rib.insert(entry1);
   BOOST_CHECK_EQUAL(rib.size(), 1);
 
-  options2.setFaceId(2);
-  rib.insert(options2);
+  RibEntry entry2;
+  entry2.name = "/hello/world";
+  entry2.faceId = 1;
+  entry2.origin = 20;
+  entry2.cost = 100;
+  entry2.flags = ndn::nfd::ROUTE_FLAG_CHILD_INHERIT;
+  entry2.expires = time::steady_clock::now() + time::seconds(0);
+
+  rib.insert(entry2);
+  BOOST_CHECK_EQUAL(rib.size(), 1);
+
+  entry2.faceId = 2;
+  rib.insert(entry2);
   BOOST_CHECK_EQUAL(rib.size(), 2);
 
-  options2.setName("/foo/bar");
-  rib.insert(options2);
+  entry2.name = "/foo/bar";
+  rib.insert(entry2);
   BOOST_CHECK_EQUAL(rib.size(), 3);
 
-  rib.erase(options2);
+  entry2.origin = 1;
+  rib.insert(entry2);
+  BOOST_CHECK_EQUAL(rib.size(), 4);
+
+  rib.erase(entry2);
+  BOOST_CHECK_EQUAL(rib.size(), 3);
+
+  entry2.name = "/hello/world";
+  rib.erase(entry2);
+  BOOST_CHECK_EQUAL(rib.size(), 3);
+
+  entry2.origin = 20;
+  rib.erase(entry2);
   BOOST_CHECK_EQUAL(rib.size(), 2);
 
-  options2.setName("/hello/world");
-  rib.erase(options2);
+  BOOST_CHECK(rib.find(entry2) == rib.end());
+  BOOST_CHECK(rib.find(entry1) != rib.end());
+
+  rib.erase(entry1);
   BOOST_CHECK_EQUAL(rib.size(), 1);
-
-  BOOST_CHECK(rib.find(options2) == rib.end());
-  BOOST_CHECK(rib.find(options1) != rib.end());
-
-  rib.erase(options1);
-  BOOST_CHECK(rib.empty());
 }
 
 BOOST_AUTO_TEST_SUITE_END()