mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-04 16:57:43 +00:00
ldpd: fix pseudowire merge algorithm
The previous algorithm wasn't failsafe for full configuration reloads where several pseudowires can be inserted or removed at the same time. This patch introduces a much simpler logic that solves the problem in a better way. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
This commit is contained in:
parent
52bd4c2321
commit
5c3f00af13
18
ldpd/l2vpn.c
18
ldpd/l2vpn.c
@ -201,6 +201,24 @@ l2vpn_pw_find(struct l2vpn *l2vpn, const char *ifname)
|
||||
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
|
||||
}
|
||||
|
||||
struct l2vpn_pw *
|
||||
l2vpn_pw_find_active(struct l2vpn *l2vpn, const char *ifname)
|
||||
{
|
||||
struct l2vpn_pw s;
|
||||
|
||||
strlcpy(s.ifname, ifname, sizeof(s.ifname));
|
||||
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_tree, &s));
|
||||
}
|
||||
|
||||
struct l2vpn_pw *
|
||||
l2vpn_pw_find_inactive(struct l2vpn *l2vpn, const char *ifname)
|
||||
{
|
||||
struct l2vpn_pw s;
|
||||
|
||||
strlcpy(s.ifname, ifname, sizeof(s.ifname));
|
||||
return (RB_FIND(l2vpn_pw_head, &l2vpn->pw_inactive_tree, &s));
|
||||
}
|
||||
|
||||
void
|
||||
l2vpn_pw_init(struct l2vpn_pw *pw)
|
||||
{
|
||||
|
@ -217,6 +217,8 @@ struct l2vpn_if *l2vpn_if_find(struct l2vpn *, const char *);
|
||||
void l2vpn_if_update(struct l2vpn_if *);
|
||||
struct l2vpn_pw *l2vpn_pw_new(struct l2vpn *, struct kif *);
|
||||
struct l2vpn_pw *l2vpn_pw_find(struct l2vpn *, const char *);
|
||||
struct l2vpn_pw *l2vpn_pw_find_active(struct l2vpn *, const char *);
|
||||
struct l2vpn_pw *l2vpn_pw_find_inactive(struct l2vpn *, const char *);
|
||||
void l2vpn_pw_init(struct l2vpn_pw *);
|
||||
void l2vpn_pw_exit(struct l2vpn_pw *);
|
||||
void l2vpn_pw_reset(struct l2vpn_pw *);
|
||||
|
72
ldpd/ldpd.c
72
ldpd/ldpd.c
@ -1591,6 +1591,22 @@ merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf)
|
||||
}
|
||||
}
|
||||
RB_FOREACH_SAFE(xl, l2vpn_head, &xconf->l2vpn_tree, ltmp) {
|
||||
struct l2vpn_pw *xp, *ptmp;
|
||||
|
||||
/* check if the pseudowires should be enabled or disabled */
|
||||
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
|
||||
if (xp->lsr_id.s_addr != INADDR_ANY && xp->pwid != 0)
|
||||
continue;
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
}
|
||||
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
|
||||
if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0)
|
||||
continue;
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &xl->pw_tree, xp);
|
||||
}
|
||||
|
||||
/* find new l2vpns */
|
||||
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) {
|
||||
RB_REMOVE(l2vpn_head, &xconf->l2vpn_tree, xl);
|
||||
@ -1624,7 +1640,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
struct l2vpn_pw *pw, *ptmp, *xp;
|
||||
struct nbr *nbr;
|
||||
int reset_nbr, reinstall_pwfec, reinstall_tnbr;
|
||||
struct l2vpn_pw_head pw_aux_list;
|
||||
int previous_pw_type, previous_mtu;
|
||||
|
||||
previous_pw_type = l2vpn->pw_type;
|
||||
@ -1656,10 +1671,9 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
}
|
||||
|
||||
/* merge active pseudowires */
|
||||
RB_INIT(&pw_aux_list);
|
||||
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_tree, ptmp) {
|
||||
/* find deleted active pseudowires */
|
||||
if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) {
|
||||
if ((xp = l2vpn_pw_find_active(xl, pw->ifname)) == NULL) {
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
l2vpn_pw_exit(pw);
|
||||
@ -1678,7 +1692,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
}
|
||||
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_tree, ptmp) {
|
||||
/* find new active pseudowires */
|
||||
if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) {
|
||||
if ((pw = l2vpn_pw_find_active(l2vpn, xp->ifname)) == NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, xp);
|
||||
xp->l2vpn = l2vpn;
|
||||
@ -1718,28 +1732,6 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
else
|
||||
reinstall_pwfec = 0;
|
||||
|
||||
/* check if the pseudowire should be disabled */
|
||||
if (xp->lsr_id.s_addr == INADDR_ANY || xp->pwid == 0) {
|
||||
reinstall_tnbr = 0;
|
||||
reset_nbr = 0;
|
||||
reinstall_pwfec = 0;
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
l2vpn_pw_exit(pw);
|
||||
break;
|
||||
case PROC_LDP_ENGINE:
|
||||
ldpe_l2vpn_pw_exit(pw);
|
||||
break;
|
||||
case PROC_MAIN:
|
||||
break;
|
||||
}
|
||||
|
||||
/* remove from active list */
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &pw_aux_list, pw);
|
||||
}
|
||||
|
||||
if (ldpd_process == PROC_LDP_ENGINE) {
|
||||
if (reinstall_tnbr)
|
||||
ldpe_l2vpn_pw_exit(pw);
|
||||
@ -1788,7 +1780,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
/* merge inactive pseudowires */
|
||||
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &l2vpn->pw_inactive_tree, ptmp) {
|
||||
/* find deleted inactive pseudowires */
|
||||
if ((xp = l2vpn_pw_find(xl, pw->ifname)) == NULL) {
|
||||
if ((xp = l2vpn_pw_find_inactive(xl, pw->ifname)) == NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
if (ldpd_process == PROC_MAIN)
|
||||
QOBJ_UNREG (pw);
|
||||
@ -1797,7 +1789,7 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
}
|
||||
RB_FOREACH_SAFE(xp, l2vpn_pw_head, &xl->pw_inactive_tree, ptmp) {
|
||||
/* find new inactive pseudowires */
|
||||
if ((pw = l2vpn_pw_find(l2vpn, xp->ifname)) == NULL) {
|
||||
if ((pw = l2vpn_pw_find_inactive(l2vpn, xp->ifname)) == NULL) {
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, xp);
|
||||
xp->l2vpn = l2vpn;
|
||||
@ -1815,34 +1807,10 @@ merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl)
|
||||
pw->ifindex = xp->ifindex;
|
||||
pw->flags = xp->flags;
|
||||
|
||||
/* check if the pseudowire should be activated */
|
||||
if (pw->lsr_id.s_addr != INADDR_ANY && pw->pwid != 0) {
|
||||
/* remove from inactive list */
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
|
||||
switch (ldpd_process) {
|
||||
case PROC_LDE_ENGINE:
|
||||
l2vpn_pw_init(pw);
|
||||
break;
|
||||
case PROC_LDP_ENGINE:
|
||||
ldpe_l2vpn_pw_init(pw);
|
||||
break;
|
||||
case PROC_MAIN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RB_REMOVE(l2vpn_pw_head, &xl->pw_inactive_tree, xp);
|
||||
free(xp);
|
||||
}
|
||||
|
||||
/* insert pseudowires that were disabled in the inactive list */
|
||||
RB_FOREACH_SAFE(pw, l2vpn_pw_head, &pw_aux_list, ptmp) {
|
||||
RB_REMOVE(l2vpn_pw_head, &l2vpn->pw_tree, pw);
|
||||
RB_INSERT(l2vpn_pw_head, &l2vpn->pw_inactive_tree, pw);
|
||||
}
|
||||
|
||||
l2vpn->pw_type = xl->pw_type;
|
||||
l2vpn->mtu = xl->mtu;
|
||||
strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname));
|
||||
|
Loading…
Reference in New Issue
Block a user