From 1fddcd0a9b05258475a8ad6e106f59887a989044 Mon Sep 17 00:00:00 2001 From: Karen Schoener Date: Wed, 27 May 2020 12:10:30 -0400 Subject: [PATCH] zebra: Every time zebra receives a ZEBRA_PW_SET, zebra should evaluate nh Every time zebra receives a ZEBRA_PW_SET, zebra should call zebra_evaluate_rnh. This fixes a race condition where zebra sometimes fails to install a pseudowire that is 'up', and has a reachable next hop. Signed-off-by: Karen Schoener --- zebra/zebra_pw.c | 9 ++++++--- zebra/zebra_rnh.c | 13 ++++++++++--- zebra/zebra_rnh.h | 2 +- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c index 273843baa2..59d69e7a36 100644 --- a/zebra/zebra_pw.c +++ b/zebra/zebra_pw.c @@ -125,9 +125,12 @@ void zebra_pw_change(struct zebra_pw *pw, ifindex_t ifindex, int type, int af, pw->flags = flags; pw->data = *data; - if (zebra_pw_enabled(pw)) - zebra_register_rnh_pseudowire(pw->vrf_id, pw); - else { + if (zebra_pw_enabled(pw)) { + bool nht_exists; + zebra_register_rnh_pseudowire(pw->vrf_id, pw, &nht_exists); + if (nht_exists) + zebra_pw_update(pw); + } else { if (pw->protocol == ZEBRA_ROUTE_STATIC) zebra_deregister_rnh_pseudowire(pw->vrf_id, pw); zebra_pw_uninstall(pw); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index ad2e00b1ec..1692a47f3e 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -343,25 +343,32 @@ static void addr2hostprefix(int af, const union g_addr *addr, } } -void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) +void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw, + bool *nht_exists) { struct prefix nh; struct rnh *rnh; bool exists; struct zebra_vrf *zvrf; + *nht_exists = false; + zvrf = vrf_info_lookup(vrf_id); if (!zvrf) return; addr2hostprefix(pw->af, &pw->nexthop, &nh); rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists); - if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { + if (!rnh) + return; + + if (!listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; zebra_evaluate_rnh(zvrf, family2afi(pw->af), 1, RNH_NEXTHOP_TYPE, &nh); - } + } else + *nht_exists = true; } void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index f07e5bc791..e744504920 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -50,7 +50,7 @@ extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, extern void zebra_free_rnh(struct rnh *rnh); extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client, enum rnh_type type, vrf_id_t vrfid); -extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *); +extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *, bool *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, enum rnh_type type);