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;