From c5f7794faa51344e4b83dfd4a1fe83cccb2fa968 Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 May 2015 18:04:16 -0700 Subject: [PATCH] Zebra: Ensure we compare prefix and NHs when checking if NH changed In nexthop tracking, the code currently compares the nexthop state of the resolved_route for a prefix with the previous nexthop state. However, if the resolved route itself changes, we can end up comparing the RIBs of unrelated prefixes and assuming that nothing has changed. To fix this, we need to store and compare the new resolved route with the previously resolved route. If this has changed, assume the NH associated with a route has changed. Signed-off-by: Dinesh G Dutt Reviewed-by: Vivek Venkataraman --- lib/prefix.c | 6 ++++++ zebra/zebra_rnh.c | 17 ++++++++++++++++- zebra/zebra_rnh.h | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/prefix.c b/lib/prefix.c index dbfdc83012..739764842d 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -278,6 +278,12 @@ prefix_copy (struct prefix *dest, const struct prefix *src) int prefix_same (const struct prefix *p1, const struct prefix *p2) { + if ((p1 && !p2) || (!p1 && p2)) + return 0; + + if (!p1 && !p2) + return 1; + if (p1->family == p2->family && p1->prefixlen == p2->prefixlen) { if (p1->family == AF_INET) diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 9b1c978ef7..380d06522b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -266,6 +266,7 @@ zebra_evaluate_rnh_table (int vrfid, int family, int force) char bufs[INET6_ADDRSTRLEN]; struct route_node *static_rn; struct nexthop *nexthop; + ntable = lookup_rnh_table(vrfid, family); if (!ntable) { @@ -312,7 +313,21 @@ zebra_evaluate_rnh_table (int vrfid, int family, int force) state_changed = 0; - if (compare_state(rib, rnh->state)) + /* Ensure prefixes we're resolving over have stayed the same */ + if (!prefix_same(&rnh->resolved_route, &prn->p)) + { + if (rib) + UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); + + if (prn) + prefix_copy(&rnh->resolved_route, &prn->p); + else + memset(&rnh->resolved_route, 0, sizeof(struct prefix)); + + copy_state(rnh, rib, nrn); + state_changed = 1; + } + else if (compare_state(rib, rnh->state)) { if (rib) UNSET_FLAG(rib->status, RIB_ENTRY_NEXTHOPS_CHANGED); diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index af56d36aaa..f18679dad3 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -33,6 +33,7 @@ struct rnh #define ZEBRA_NHT_CONNECTED 0x1 #define ZEBRA_NHT_DELETED 0x2 struct rib *state; + struct prefix resolved_route; struct list *client_list; struct list *zebra_static_route_list; /* static routes dependent on this NH */ struct route_node *node;