From: Renato Westphal Date: Wed, 1 Mar 2023 20:31:56 +0000 (-0300) Subject: ospf6d: update DR election to handle GR corner case X-Git-Tag: base_9.0~313^2~5 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e23e56831958c3ae373a56a13ab8e0fc46fe6413;p=mirror%2Ffrr.git ospf6d: update DR election to handle GR corner case Consider the case where a DR router is performing a graceful restart, and all neighbors attached to the DR network have their priorities set to zero. According to RFC 3623, the router should reclaim its DR status while coming back up once it receives a Hello packet from a neighbor listing the router as the DR, and the associated interface is in Waiting state. The problem arises when the DR election starts. Since the router is already elected the DR, and no BDR will be elected (since all neighbors have their priorities set to zero), the AdjOk event won't be triggered at the end of the DR election as it would normally happen. That causes all neighbors reachable over the broadcast interface to get stuck in the 2-Way state. Fix this corner case by always triggering the AdjOk event at the end of the DR election process when a GR is in progress. Triggering the AdjOk event when not necessary should never be a problem as the neighbor FSM is already prepared to deal with that. Signed-off-by: Renato Westphal --- 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,