forked from Mirror/frr
ldpd: fix issues with dual-stack adjacencies
Handling configuration changes from single-stack mode to dual-stack mode (and vice-versa) is tricky. This patch attempts to solve all issues that might happen on such circumstances. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
98f65fda88
commit
0e3451e5cf
|
@ -109,17 +109,19 @@ adj_new(struct in_addr lsr_id, struct hello_source *source,
|
||||||
return (adj);
|
return (adj);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
adj_del_single(struct adj *adj)
|
adj_del(struct adj *adj, uint32_t notif_status)
|
||||||
{
|
{
|
||||||
|
struct nbr *nbr = adj->nbr;
|
||||||
|
|
||||||
log_debug("%s: lsr-id %s, %s (%s)", __func__, inet_ntoa(adj->lsr_id),
|
log_debug("%s: lsr-id %s, %s (%s)", __func__, inet_ntoa(adj->lsr_id),
|
||||||
log_hello_src(&adj->source), af_name(adj_get_af(adj)));
|
log_hello_src(&adj->source), af_name(adj_get_af(adj)));
|
||||||
|
|
||||||
adj_stop_itimer(adj);
|
adj_stop_itimer(adj);
|
||||||
|
|
||||||
RB_REMOVE(global_adj_head, &global.adj_tree, adj);
|
RB_REMOVE(global_adj_head, &global.adj_tree, adj);
|
||||||
if (adj->nbr)
|
if (nbr)
|
||||||
RB_REMOVE(nbr_adj_head, &adj->nbr->adj_tree, adj);
|
RB_REMOVE(nbr_adj_head, &nbr->adj_tree, adj);
|
||||||
switch (adj->source.type) {
|
switch (adj->source.type) {
|
||||||
case HELLO_LINK:
|
case HELLO_LINK:
|
||||||
RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
|
RB_REMOVE(ia_adj_head, &adj->source.link.ia->adj_tree, adj);
|
||||||
|
@ -130,15 +132,6 @@ adj_del_single(struct adj *adj)
|
||||||
}
|
}
|
||||||
|
|
||||||
free(adj);
|
free(adj);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
adj_del(struct adj *adj, uint32_t notif_status)
|
|
||||||
{
|
|
||||||
struct nbr *nbr = adj->nbr;
|
|
||||||
struct adj *atmp;
|
|
||||||
|
|
||||||
adj_del_single(adj);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the neighbor still exists but none of its remaining
|
* If the neighbor still exists but none of its remaining
|
||||||
|
@ -146,8 +139,6 @@ adj_del(struct adj *adj, uint32_t notif_status)
|
||||||
* then delete it.
|
* then delete it.
|
||||||
*/
|
*/
|
||||||
if (nbr && nbr_adj_count(nbr, nbr->af) == 0) {
|
if (nbr && nbr_adj_count(nbr, nbr->af) == 0) {
|
||||||
RB_FOREACH_SAFE(adj, nbr_adj_head, &nbr->adj_tree, atmp)
|
|
||||||
adj_del_single(adj);
|
|
||||||
session_shutdown(nbr, notif_status, 0, 0);
|
session_shutdown(nbr, notif_status, 0, 0);
|
||||||
nbr_del(nbr);
|
nbr_del(nbr);
|
||||||
}
|
}
|
||||||
|
@ -194,7 +185,6 @@ adj_itimer(struct thread *thread)
|
||||||
tnbr_del(leconf, adj->source.target);
|
tnbr_del(leconf, adj->source.target);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
adj->source.target->adj = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adj_del(adj, S_HOLDTIME_EXP);
|
adj_del(adj, S_HOLDTIME_EXP);
|
||||||
|
|
17
ldpd/hello.c
17
ldpd/hello.c
|
@ -214,6 +214,7 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
||||||
__func__, inet_ntoa(lsr_id));
|
__func__, inet_ntoa(lsr_id));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ds_tlv = (tlvs_rcvd & F_HELLO_TLV_RCVD_DS) ? 1 : 0;
|
||||||
|
|
||||||
/* implicit transport address */
|
/* implicit transport address */
|
||||||
if (!(tlvs_rcvd & F_HELLO_TLV_RCVD_ADDR))
|
if (!(tlvs_rcvd & F_HELLO_TLV_RCVD_ADDR))
|
||||||
|
@ -291,11 +292,21 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
||||||
source.link.src_addr = *src;
|
source.link.src_addr = *src;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug_hello_recv("%s lsr-id %s transport-address %s holdtime %u%s",
|
||||||
|
log_hello_src(&source), inet_ntoa(lsr_id), log_addr(af, &trans_addr),
|
||||||
|
holdtime, (ds_tlv) ? " (dual stack TLV present)" : "");
|
||||||
|
|
||||||
adj = adj_find(lsr_id, &source);
|
adj = adj_find(lsr_id, &source);
|
||||||
|
if (adj && adj->ds_tlv != ds_tlv) {
|
||||||
|
/*
|
||||||
|
* Transient condition, ignore packet and wait until adjacency
|
||||||
|
* times out.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
nbr = nbr_find_ldpid(lsr_id.s_addr);
|
nbr = nbr_find_ldpid(lsr_id.s_addr);
|
||||||
|
|
||||||
/* check dual-stack tlv */
|
/* check dual-stack tlv */
|
||||||
ds_tlv = (tlvs_rcvd & F_HELLO_TLV_RCVD_DS) ? 1 : 0;
|
|
||||||
if (ds_tlv && trans_pref != leconf->trans_pref) {
|
if (ds_tlv && trans_pref != leconf->trans_pref) {
|
||||||
/*
|
/*
|
||||||
* RFC 7552 - Section 6.1.1:
|
* RFC 7552 - Section 6.1.1:
|
||||||
|
@ -420,10 +431,6 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *msg, int af,
|
||||||
else
|
else
|
||||||
adj_stop_itimer(adj);
|
adj_stop_itimer(adj);
|
||||||
|
|
||||||
debug_hello_recv("%s lsr-id %s transport-address %s holdtime %u%s",
|
|
||||||
log_hello_src(&source), inet_ntoa(lsr_id), log_addr(af, &trans_addr),
|
|
||||||
holdtime, (ds_tlv) ? " (dual stack TLV present)" : "");
|
|
||||||
|
|
||||||
if (nbr && nbr->state == NBR_STA_PRESENT && !nbr_pending_idtimer(nbr) &&
|
if (nbr && nbr->state == NBR_STA_PRESENT && !nbr_pending_idtimer(nbr) &&
|
||||||
nbr_session_active_role(nbr) && !nbr_pending_connect(nbr))
|
nbr_session_active_role(nbr) && !nbr_pending_connect(nbr))
|
||||||
nbr_establish_connection(nbr);
|
nbr_establish_connection(nbr);
|
||||||
|
|
Loading…
Reference in a new issue