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 = summary->path.origin.id =
ADV_ROUTER_IN_PREFIX(&route->prefix); ADV_ROUTER_IN_PREFIX(&route->prefix);
} else { } else {
struct ospf6_lsa *old;
summary->path.origin.type = summary->path.origin.type =
htons(OSPF6_LSTYPE_INTER_PREFIX); htons(OSPF6_LSTYPE_INTER_PREFIX);
/* 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.id = ospf6_new_ls_id(
summary->path.origin.type, summary->path.origin.type,
summary->path.origin.adv_router, area->lsdb); summary->path.origin.adv_router,
area->lsdb);
} }
summary = ospf6_route_add(summary, summary_table); summary = ospf6_route_add(summary, summary_table);
} else { } else {

View File

@ -1105,9 +1105,12 @@ void ospf6_receive_lsa(struct ospf6_neighbor *from,
&new->refresh); &new->refresh);
} }
/* GR: check for network topology change. */
struct ospf6 *ospf6 = from->ospf6_if->area->ospf6; struct ospf6 *ospf6 = from->ospf6_if->area->ospf6;
struct ospf6_area *area = from->ospf6_if->area; 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); ospf6_gr_check_lsdb_consistency(ospf6, area);
return; return;

View File

@ -127,6 +127,7 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
{ {
struct ospf6_area *area; struct ospf6_area *area;
struct listnode *onode, *anode; struct listnode *onode, *anode;
struct ospf6_route *route;
if (IS_DEBUG_OSPF6_GR) if (IS_DEBUG_OSPF6_GR)
zlog_debug("GR: exiting graceful restart: %s", reason); zlog_debug("GR: exiting graceful restart: %s", reason);
@ -148,7 +149,15 @@ static void ospf6_gr_restart_exit(struct ospf6 *ospf6, const char *reason)
*/ */
OSPF6_ROUTER_LSA_EXECUTE(area); 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)) { for (ALL_LIST_ELEMENTS_RO(area->if_list, anode, oi)) {
/* Reoriginate Link-LSA. */
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
OSPF6_LINK_LSA_EXECUTE(oi); OSPF6_LINK_LSA_EXECUTE(oi);
/* /*
@ -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 * 3) The router reruns its OSPF routing calculations, this time
* installing the results into the system forwarding table, and * 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) uint8_t dr_election(struct ospf6_interface *oi)
{ {
struct ospf6 *ospf6 = oi->area->ospf6;
struct listnode *node, *nnode; struct listnode *node, *nnode;
struct ospf6_neighbor *on, *drouter, *bdrouter, myself; struct ospf6_neighbor *on, *drouter, *bdrouter, myself;
struct ospf6_neighbor *best_drouter, *best_bdrouter; 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) */ /* pseudo neighbor myself, including noting current DR/BDR (1) */
memset(&myself, 0, sizeof(myself)); memset(&myself, 0, sizeof(myself));
inet_ntop(AF_INET, &oi->area->ospf6->router_id, myself.name, inet_ntop(AF_INET, &ospf6->router_id, myself.name, sizeof(myself.name));
sizeof(myself.name));
myself.state = OSPF6_NEIGHBOR_TWOWAY; myself.state = OSPF6_NEIGHBOR_TWOWAY;
myself.drouter = oi->drouter; myself.drouter = oi->drouter;
myself.bdrouter = oi->bdrouter; myself.bdrouter = oi->bdrouter;
myself.priority = oi->priority; myself.priority = oi->priority;
myself.router_id = oi->area->ospf6->router_id; myself.router_id = ospf6->router_id;
/* Electing BDR (2) */ /* Electing BDR (2) */
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) 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) */ /* If DR or BDR change, invoke AdjOK? for each neighbor (7) */
/* RFC 2328 section 12.4. Originating LSAs (3) will be handled /* RFC 2328 section 12.4. Originating LSAs (3) will be handled
accordingly after AdjOK */ 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) if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("DR Election on %s: DR: %s BDR: %s", zlog_debug("DR Election on %s: DR: %s BDR: %s",
oi->interface->name, oi->interface->name,

View File

@ -13,8 +13,10 @@
#include "vty.h" #include "vty.h"
#include "ospf6_proto.h" #include "ospf6_proto.h"
#include "ospf6_area.h"
#include "ospf6_lsa.h" #include "ospf6_lsa.h"
#include "ospf6_lsdb.h" #include "ospf6_lsdb.h"
#include "ospf6_abr.h"
#include "ospf6_asbr.h" #include "ospf6_asbr.h"
#include "ospf6_route.h" #include "ospf6_route.h"
#include "ospf6d.h" #include "ospf6d.h"
@ -216,6 +218,31 @@ struct ospf6_lsa *ospf6_find_external_lsa(struct ospf6 *ospf6, struct prefix *p)
return lsa; 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, struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router, uint32_t adv_router,
struct ospf6_lsdb *lsdb) 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, extern struct ospf6_lsa *ospf6_lsdb_lookup_next(uint16_t type, uint32_t id,
uint32_t adv_router, uint32_t adv_router,
struct ospf6_lsdb *lsdb); 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_add(struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb);
extern void ospf6_lsdb_remove(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) if (ospf_flood(oi->ospf, nbr, current, lsa)
< 0) /* Trap NSSA later. */ < 0) /* Trap NSSA later. */
DISCARD_LSA(lsa, 5); 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; continue;
} }
@ -2214,9 +2222,6 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
assert(listcount(lsas) == 0); assert(listcount(lsas) == 0);
list_delete(&lsas); 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. */ /* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */