From: Renato Westphal Date: Thu, 24 Nov 2022 01:14:51 +0000 (-0300) Subject: ospf6d: fix infinite loop when adding ASBR route X-Git-Tag: base_8.5~205^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=4dfe15200ab1a84a8d77fcbc33085c373d556eae;p=matthieu%2Ffrr.git ospf6d: fix infinite loop when adding ASBR route Commit 8f359e1593c414322 removed a check that prevented the same route from being added twice. In certain topologies, that change resulted in the following infinite loop when adding an ASBR route: ospf6_route_add ospf6_top_brouter_hook_add ospf6_abr_examin_brouter ospf6_abr_examin_summary ospf6_route_add (repeat until stack overflow) Revert the offending commit and update `ospf6_route_is_identical()` to not do comparison using `memcmp()`. Signed-off-by: Renato Westphal --- diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c index db94b85b1b..1cc1fcb47b 100644 --- a/ospf6d/ospf6_route.c +++ b/ospf6d/ospf6_route.c @@ -702,6 +702,27 @@ struct ospf6_route *ospf6_route_add(struct ospf6_route *route, } if (old) { + /* if route does not actually change, return unchanged */ + if (ospf6_route_is_identical(old, route)) { + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) + zlog_debug( + "%s %p: route add %p: needless update of %p old cost %u", + ospf6_route_table_name(table), + (void *)table, (void *)route, + (void *)old, old->path.cost); + else if (IS_OSPF6_DEBUG_ROUTE(TABLE)) + zlog_debug("%s: route add: needless update", + ospf6_route_table_name(table)); + + ospf6_route_delete(route); + SET_FLAG(old->flag, OSPF6_ROUTE_ADD); + ospf6_route_table_assert(table); + + /* to free the lookup lock */ + route_unlock_node(node); + return old; + } + if (IS_OSPF6_DEBUG_ROUTE(MEMORY)) zlog_debug( "%s %p: route add %p cost %u paths %u nh %u: update of %p cost %u paths %u nh %u", diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h index bb5827a176..c8411c015f 100644 --- a/ospf6d/ospf6_route.h +++ b/ospf6d/ospf6_route.h @@ -297,6 +297,14 @@ extern const char *const ospf6_path_type_substr[OSPF6_PATH_TYPE_MAX]; && (ra)->path.origin.type == (rb)->path.origin.type \ && (ra)->path.origin.id == (rb)->path.origin.id \ && (ra)->path.origin.adv_router == (rb)->path.origin.adv_router) +#define ospf6_route_is_identical(ra, rb) \ + ((ra)->type == (rb)->type && \ + prefix_same(&(ra)->prefix, &(rb)->prefix) && \ + (ra)->path.type == (rb)->path.type && \ + (ra)->path.cost == (rb)->path.cost && \ + (ra)->path.u.cost_e2 == (rb)->path.u.cost_e2 && \ + listcount(ra->paths) == listcount(rb->paths) && \ + ospf6_route_cmp_nexthops(ra, rb) == 0) #define ospf6_route_is_best(r) (CHECK_FLAG ((r)->flag, OSPF6_ROUTE_BEST))