summaryrefslogtreecommitdiffstats
path: root/ldpd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2017-03-26 00:57:03 +0100
committerRenato Westphal <renato@opensourcerouting.org>2017-03-27 19:54:57 +0200
commit5c3f00af13f1ac4f61dc7126741f7fd6e032151f (patch)
tree4bff947c7d2e86914200ff4b5423737d84ffb516 /ldpd
parentldpd: remove a few unnecessary functions (diff)
downloadfrr-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.c18
-rw-r--r--ldpd/lde.h2
-rw-r--r--ldpd/ldpd.c72
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));