Bug #2177
closed
INVALID_FACE_ID appears in FIB
Added by Junxiao Shi about 10 years ago.
Updated almost 10 years ago.
Description
Steps to reproduce:
- start NFD
- 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();
}
- press CTRL+C to kill the program in step 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)}
- Has duplicate Bug #1812: INVALID_FACE_ID appears in FIB added
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);
}
Alex/Junxiao: who's the right person to fix this problem?
It's too early to talk about assignment. We need to know the cause of this problem before deciding who to assign.
Can whoever wrote the code mentioned in note 2 figure out the problem?
- 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.
- 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.
- Status changed from In Progress to Code review
- % Done changed from 20 to 100
- Status changed from Code review to Closed
Also available in: Atom
PDF