ldpd: fix bug with dual-stack neighbors

We were assuming that a neighbor can be deleted only when all of its
adjacencies are dead. This is not the case for dual-stack neighbors. If
the transport-preference is IPv4 and all adjacencies are IPv6 (or
vice-versa), then it should be deleted and everything cleaned-up
accordingly.

Bug exposed by the new RB tree implementation on master, but the fix
also applies to stable/3.0.

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
Renato Westphal 2017-07-24 18:57:20 -03:00
parent 1e4d264f2b
commit 69f93be55a

View File

@ -287,6 +287,8 @@ nbr_new(struct in_addr id, int af, int ds_tlv, union ldpd_addr *addr,
void void
nbr_del(struct nbr *nbr) nbr_del(struct nbr *nbr)
{ {
struct adj *adj;
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id)); log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION); nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
@ -312,6 +314,11 @@ nbr_del(struct nbr *nbr)
mapping_list_clr(&nbr->release_list); mapping_list_clr(&nbr->release_list);
mapping_list_clr(&nbr->abortreq_list); mapping_list_clr(&nbr->abortreq_list);
while ((adj = RB_ROOT(&nbr->adj_tree)) != NULL) {
adj->nbr = NULL;
RB_REMOVE(nbr_adj_head, &nbr->adj_tree, adj);
}
if (nbr->peerid) if (nbr->peerid)
RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr); RB_REMOVE(nbr_pid_head, &nbrs_by_pid, nbr);
RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr); RB_REMOVE(nbr_id_head, &nbrs_by_id, nbr);