I have not yet checked how other implementations handle the situation where an update with a as-path loop hides the fact that the neighbor just lost a path.
But I made a quick patch if anyone feel like testing. The black-hole condition does not appear anymore when I test. Be gentle, I only browsed through the code while on the underground to and from work. /Tony Index: rde.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v retrieving revision 1.228 diff -r1.228 rde.c 922,927d921 < /* aspath needs to be loop free nota bene this is not a hard error */ < if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, conf->as)) { < error = 0; < goto done; < } < 957,959c951,961 < if (peer->conf.softreconfig_in) < path_update(peer, asp, &prefix, prefixlen, F_ORIGINAL); < --- > if (peer->conf.softreconfig_in) { > /* handle an update with loop as a withdraw */ > if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, > conf->as)) > prefix_remove(peer, &prefix, prefixlen, > F_ORIGINAL); > else > path_update(peer, asp, &prefix, prefixlen, > F_ORIGINAL); > > } 980,983c982,993 < rde_update_log("update", peer, &fasp->nexthop->exit_nexthop, < &prefix, prefixlen); < path_update(peer, fasp, &prefix, prefixlen, F_LOCAL); < --- > rde_update_log("update", peer, > &fasp->nexthop->exit_nexthop,&prefix, > prefixlen); > /* handle an update with loop as a withdraw */ > if (peer->conf.ebgp && !aspath_loopfree(asp->aspath, > conf->as)) > prefix_remove(peer, &prefix, prefixlen, > F_LOCAL); > else > path_update(peer, fasp, &prefix, prefixlen, > F_LOCAL); > 1050,1053c1060,1069 < if (peer->conf.softreconfig_in) < path_update(peer, asp, &prefix, < prefixlen, F_ORIGINAL); < --- > if (peer->conf.softreconfig_in) { > /* handle an update with loop as a withdraw */ > if (peer->conf.ebgp && > > !aspath_loopfree(asp->aspath,conf->as)) > prefix_remove(peer, &prefix, > prefixlen,F_ORIGINAL); > else > path_update(peer, asp, &prefix, > prefixlen, F_ORIGINAL); > } 1078,1080c1094,1102 < &prefix, prefixlen); < path_update(peer, fasp, &prefix, prefixlen, < F_LOCAL); --- > &prefix, prefixlen); > /* handle an update with loop as a withdraw */ > if (peer->conf.ebgp && > !aspath_loopfree(asp->aspath,conf->as)) > prefix_remove(peer, &prefix, > prefixlen,F_LOCAL); > else > path_update(peer, fasp, &prefix, > prefixlen,F_LOCAL);