diff options
author | Renato Westphal <renato@opensourcerouting.org> | 2017-03-26 00:57:03 +0100 |
---|---|---|
committer | Renato Westphal <renato@opensourcerouting.org> | 2017-03-27 19:54:57 +0200 |
commit | 5c3f00af13f1ac4f61dc7126741f7fd6e032151f (patch) | |
tree | 4bff947c7d2e86914200ff4b5423737d84ffb516 /ldpd | |
parent | ldpd: remove a few unnecessary functions (diff) | |
download | frr-5c3f00af13f1ac4f61dc7126741f7fd6e032151f.tar.xz frr-5c3f00af13f1ac4f61dc7126741f7fd6e032151f.zip |
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>
Diffstat (limited to 'ldpd')
-rw-r--r-- | ldpd/l2vpn.c | 18 | ||||
-rw-r--r-- | ldpd/lde.h | 2 | ||||
-rw-r--r-- | ldpd/ldpd.c | 72 |
3 files changed, 40 insertions, 52 deletions
diff --git a/ldpd/l2vpn.c b/ldpd/l2vpn.c index 29302c465..ca40636e0 100644 --- a/ldpd/l2vpn.c +++ b/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) { diff --git a/ldpd/lde.h b/ldpd/lde.h index 9ab20e45e..d1089b44f 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -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 *); diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 0f18c6e31..3023d9446 100644 --- a/ldpd/ldpd.c +++ b/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)); |