Project

General

Profile

Bug #2177

INVALID_FACE_ID appears in FIB

Added by Junxiao Shi almost 5 years ago. Updated almost 5 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Tables
Target version:
Start date:
11/13/2014
Due date:
% Done:

100%

Estimated time:

Description

Steps to reproduce:

  1. start NFD
  2. run this code snippet:
#include <ndn-cxx/face.hpp>

using namespace ndn;

int main(int argc, char** argv)
{
  Face face;
  for (int i = 0; i < 300; ++i) {
    Name prefix("/localhost/app");
    prefix.appendVersion(i);
    face.registerPrefix(prefix,
                        bind([i] { std::cout << "SUCCESS " << i << std::endl; }),
                        bind([i] { std::cout << "FAILURE " << i << std::endl; })
                        );
  }
  face.processEvents();
}
  1. press CTRL+C to kill the program in step 2
  2. look at FIB with nfd-status -b

Expected: prefixes registered by the program are erased

Actual: /localhost/app/%FD%BC nexthops={faceid=18446744073709551615 (cost=0)}


Related issues

Has duplicate NFD - Bug #1812: INVALID_FACE_ID appears in FIBAbandoned2014-07-31

History

#1 Updated by Junxiao Shi almost 5 years ago

  • Has duplicate Bug #1812: INVALID_FACE_ID appears in FIB added

#2 Updated by Vince Lehman almost 5 years ago

I'm not sure of the cause but it looks like there is an issue with something called in "Fib::removeNextHopFromAllEntries".

If you add these debug messages to the code:

void
Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
{
  for (NameTree::const_iterator it = m_nameTree.fullEnumerate(
       &predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end();) {
       shared_ptr<fib::Entry> entry = it->getFibEntry();

    ++it; // advance the iterator before `erase` invalidates it

    std::cout << "Before " << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;
    entry->removeNextHop(face);
    std::cout << "After " << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;

    if (!entry->hasNextHops()) {
      this->erase(*entry);
    }
  }

  std::cout << "After NextHop removal" << std::endl;
  for (NameTree::const_iterator it = m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry);
       it != m_nameTree.end(); ++it) 
  {
    shared_ptr<fib::Entry> entry = it->getFibEntry();
    std::cout << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;
  }
}

You get:

...
Before /localhost/app/%FD%04: 1
After /localhost/app/%FD%04: 0
Before /localhost/app/%FD%01%24: 1
After /localhost/app/%FD%01%24: 0
After NextHop removal
/localhost/app/%FD%CD: 1
/localhost/app/%FDc: 1
/localhost/app/%FDS: 1
/localhost/app/%FD%A9: 1
/localhost/app/%FD%01: 1
/localhost/app/%FD%1D: 1
/localhost/app/%FDH: 1
...

So, it looks like the nexthops are not being removed and an invalid face is assigned to them by the FaceTable:

void
FaceTable::remove(shared_ptr<Face> face)
{
  ...
  face->setId(INVALID_FACEID);
  ...
  m_forwarder.getFib().removeNextHopFromAllEntries(face);
}

#3 Updated by Lan Wang almost 5 years ago

Alex/Junxiao: who's the right person to fix this problem?

#4 Updated by Junxiao Shi almost 5 years ago

It's too early to talk about assignment. We need to know the cause of this problem before deciding who to assign.

#5 Updated by Lan Wang almost 5 years ago

Can whoever wrote the code mentioned in note 2 figure out the problem?

#6 Updated by Junxiao Shi almost 5 years ago

  • Assignee set to Junxiao Shi

I'll investigate this problem.

Since it doesn't affect normal applications that register only a few prefixes, this is not urgent.

#7 Updated by Junxiao Shi almost 5 years ago

  • Status changed from New to In Progress
  • % Done changed from 0 to 20

This Bug is due to Fib::removeNextHopFromAllEntries's incorrect usage of NameTree iterators.

NameTree full enumeration iterators may be invalidated whenever there is a NameTree entry insertion or deletion.
Full enumeration iterators are tied to buckets, but an insertion or deletion may cause NameTree to resize its hashtable, where nodes are rehashed into new buckets.

This can be confirmed by observing that this->size() at the top of Fib::removeNextHopFromAllEntries differs from the number of loop body executions.

#8 Updated by Junxiao Shi almost 5 years ago

  • Status changed from In Progress to Code review
  • % Done changed from 20 to 100

#9 Updated by Junxiao Shi almost 5 years ago

  • Status changed from Code review to Closed

Also available in: Atom PDF