Merge pull request #12922 from opensourcerouting/ospf-gr-fixes

OSPF Graceful Restart fixes
This commit is contained in:
Russ White 2023-03-14 08:38:36 -04:00 committed by GitHub
commit 4c88ac57d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 82 additions and 13 deletions

View File

@ -515,11 +515,21 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
summary->path.origin.id =
ADV_ROUTER_IN_PREFIX(&route->prefix);
} else {
struct ospf6_lsa *old;
summary->path.origin.type =
htons(OSPF6_LSTYPE_INTER_PREFIX);
summary->path.origin.id = ospf6_new_ls_id(
summary->path.origin.type,
summary->path.origin.adv_router, area->lsdb);
/* Try to reuse LS-ID from previous running instance. */
old = ospf6_find_inter_prefix_lsa(area->ospf6, area,
&route->prefix);
if (old)
summary->path.origin.id = old->header->id;
else
summary->path.origin.id = ospf6_new_ls_id(
summary->path.origin.type,
summary->path.origin.adv_router,
area->lsdb);
}
summary = ospf6_route_add(summary, summary_table);
} else {

View File

@ -1105,9 +1105,12 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
&new->refresh);
}
/* GR: check for network topology change. */
struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
struct ospf6_area *area = from->ospf6_if->area;
if (ospf6->gr_info.restart_in_progress)
if (ospf6->gr_info.restart_in_progress &&
(new->header->type == ntohs(OSPF6_LSTYPE_ROUTER) ||
new->header->type == ntohs(OSPF6_LSTYPE_NETWORK)))
ospf6_gr_check_lsdb_consistency(ospf6, area);
return;

View File

@ -127,6 +127,7 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
{
struct ospf6_area *area;
struct listnode *onode, *anode;
struct ospf6_route *route;
if (IS_DEBUG_OSPF6_GR)
zlog_debug("GR: exiting graceful restart: %s", reason);
@ -148,8 +149,16 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
*/
OSPF6_ROUTER_LSA_EXECUTE(area);
/*
* Force reorigination of intra-area-prefix-LSAs to handle
* areas without any full adjacency.
*/
OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(area);
for (ALL_LIST_ELEMENTS_RO(area->if_list, anode, oi)) {
OSPF6_LINK_LSA_EXECUTE(oi);
/* Reoriginate Link-LSA. */
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
OSPF6_LINK_LSA_EXECUTE(oi);
/*
* 2) The router should reoriginate network-LSAs on all
@ -160,6 +169,16 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
}
}
/*
* While all self-originated NSSA and AS-external LSAs were already
* learned from the helping neighbors, we need to reoriginate them in
* order to ensure they will be refreshed periodically.
*/
for (route = ospf6_route_head(ospf6->external_table); route;
route = ospf6_route_next(route))
ospf6_handle_external_lsa_origination(ospf6, route,
&route->prefix);
/*
* 3) The router reruns its OSPF routing calculations, this time
* installing the results into the system forwarding table, and

View File

@ -592,6 +592,7 @@ static struct ospf6_neighbor *better_drouter(struct ospf6_neighbor *a,
uint8_t dr_election(struct ospf6_interface *oi)
{
struct ospf6 *ospf6 = oi->area->ospf6;
struct listnode *node, *nnode;
struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
struct ospf6_neighbor *best_drouter, *best_bdrouter;
@ -602,13 +603,12 @@ uint8_t dr_election(struct ospf6_interface *oi)
/* pseudo neighbor myself, including noting current DR/BDR (1) */
memset(&myself, 0, sizeof(myself));
inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name,
sizeof(myself.name));
inet_ntop(AF_INET, &ospf6->router_id, myself.name, sizeof(myself.name));
myself.state = OSPF6_NEIGHBOR_TWOWAY;
myself.drouter = oi->drouter;
myself.bdrouter = oi->bdrouter;
myself.priority = oi->priority;
myself.router_id = oi->area->ospf6->router_id;
myself.router_id = ospf6->router_id;
/* Electing BDR (2) */
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on))
@ -657,8 +657,10 @@ uint8_t dr_election(struct ospf6_interface *oi)
/* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
/* RFC 2328 section 12.4. Originating LSAs (3) will be handled
accordingly after AdjOK */
if (oi->drouter != (drouter ? drouter->router_id : htonl(0))
|| oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0))) {
if (oi->drouter != (drouter ? drouter->router_id : htonl(0)) ||
oi->bdrouter != (bdrouter ? bdrouter->router_id : htonl(0)) ||
ospf6->gr_info.restart_in_progress) {
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("DR Election on %s: DR: %s BDR: %s",
oi->interface->name,

View File

@ -13,8 +13,10 @@
#include "vty.h"
#include "ospf6_proto.h"
#include "ospf6_area.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
#include "ospf6_abr.h"
#include "ospf6_asbr.h"
#include "ospf6_route.h"
#include "ospf6d.h"
@ -216,6 +218,31 @@ struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
return lsa;
}
struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
struct ospf6_area *area,
struct prefix *p)
{
struct ospf6_lsa *lsa;
uint16_t type = htons(OSPF6_LSTYPE_INTER_PREFIX);
for (ALL_LSDB_TYPED_ADVRTR(area->lsdb, type, ospf6->router_id, lsa)) {
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct prefix prefix;
prefix_lsa =
(struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
lsa->header);
prefix.family = AF_INET6;
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
&prefix_lsa->prefix);
if (prefix_same(p, &prefix))
return lsa;
}
return NULL;
}
struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router,
struct ospf6_lsdb *lsdb)

View File

@ -29,6 +29,9 @@ extern struct ospf6_lsa *ospf6_lsdb_lookup(uint16_t type, uint32_t id,
extern struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router,
struct ospf6_lsdb *lsdb);
extern struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
struct ospf6_area *area,
struct prefix *p);
extern void ospf6_lsdb_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
extern void ospf6_lsdb_remove(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);

View File

@ -2102,6 +2102,14 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
if (ospf_flood(oi->ospf, nbr, current, lsa)
< 0) /* Trap NSSA later. */
DISCARD_LSA(lsa, 5);
/* GR: check for network topology change. */
if (ospf->gr_info.restart_in_progress &&
((lsa->data->type == OSPF_ROUTER_LSA ||
lsa->data->type == OSPF_NETWORK_LSA)))
ospf_gr_check_lsdb_consistency(oi->ospf,
oi->area);
continue;
}
@ -2214,9 +2222,6 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
assert(listcount(lsas) == 0);
list_delete(&lsas);
if (ospf->gr_info.restart_in_progress)
ospf_gr_check_lsdb_consistency(oi->ospf, oi->area);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */