diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index 4def3c7386..5b2b204dd8 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -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 { diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c index 2d2069566c..db1520ff20 100644 --- a/ospf6d/ospf6_flood.c +++ b/ospf6d/ospf6_flood.c @@ -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; diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c index c182e48f2e..847531361e 100644 --- a/ospf6d/ospf6_gr.c +++ b/ospf6d/ospf6_gr.c @@ -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 diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 7a22fdf064..7afb47c752 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -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, diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index 0221102b59..586183731c 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -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) diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h index 7e20b05447..a2444f1c14 100644 --- a/ospf6d/ospf6_lsdb.h +++ b/ospf6d/ospf6_lsdb.h @@ -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); diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 5268c9896b..2937c4ec0c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -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. */