Skip to content

ospf6d: Remove ospf6 route when connected wins - #21476

Merged
Jafaral merged 1 commit into
FRRouting:masterfrom
donaldsharp:ospf6_connected_wins
Apr 8, 2026
Merged

ospf6d: Remove ospf6 route when connected wins#21476
Jafaral merged 1 commit into
FRRouting:masterfrom
donaldsharp:ospf6_connected_wins

Conversation

@donaldsharp

Copy link
Copy Markdown
Member

Currently when ospf6 installs a route that is later covered by a connected, the ospf6 route is never removed. Modify the code to detect the case where the new route that wins in ospf6 notices that it is connected and the old route that was in was a ospf6 route. If so send a specific route deletion for the ospf6 route.

This failure is happening infrequently in the ospf6_point_to_multipoint test due to timing issues on how connected routes are received into ospf6.

@donaldsharp

donaldsharp commented Apr 8, 2026

Copy link
Copy Markdown
Member Author

Note for me the ospf6_point_to_multipoint test fails infrequently ( between 1-8 times when running in parallel with itself 64 times ). Now it never fails. The test was failing with a unexpected ospf6 route in the zebra rib.

From my perspective this is also more of a display bug than anything else. The ospf6 route is going to sit there and do nothing because it is just going to exist in zebra but never be selected.

@greptile-apps

greptile-apps Bot commented Apr 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a bug in ospf6d where an OSPF6 route installed in zebra is never removed when a connected route later wins in the OSPF6 routing table. The fix adds logic in ospf6_route_add to detect when the incoming winning route is a connected route and the displaced best route was an OSPF6 route, then explicitly sends a ZEBRA_ROUTE_DELETE to zebra for that prefix. A new helper function ospf6_zebra_route_delete_prefix is introduced in ospf6_zebra.c and declared in ospf6_zebra.h.

Key changes:

  • ospf6_route.c: In the "another path found" branch of ospf6_route_add, detects when a connected route replaces a non-connected (OSPF6) route as the best path and triggers an explicit zebra deletion.
  • ospf6_zebra.c: Adds ospf6_zebra_route_delete_prefix, which sends a bare ZEBRA_ROUTE_DELETE (prefix + type, no nexthops) via zclient_route_send, with flog_err on failure.
  • ospf6_zebra.h: Exports the new function declaration.

The fix is well-targeted and addresses a race condition seen in the ospf6_point_to_multipoint test. Prior review concerns (GR guard, return-value checking) have been addressed per maintainer guidance.

Confidence Score: 5/5

This PR is safe to merge; the fix is well-scoped and correctly handles the stale-route edge case.

The change is small, targeted, and addresses a real bug. Prior review concerns (GR guard, send return value) have been resolved per maintainer guidance. The logic in ospf6_route_add correctly guards with scope type and connected/non-connected checks. No P0 or P1 findings remain.

No files require special attention.

Vulnerabilities

No security concerns identified.

Important Files Changed

Filename Overview
ospf6d/ospf6_route.c Adds connected-wins detection in ospf6_route_add; condition correctly checks route->connected && !next->connected with GLOBAL scope guard before calling new delete helper.
ospf6d/ospf6_zebra.c Adds ospf6_zebra_route_delete_prefix; sends ZEBRA_ROUTE_DELETE by prefix/type without nexthops, with error logging on failure β€” consistent with zebra deletion semantics.
ospf6d/ospf6_zebra.h Adds extern declaration for ospf6_zebra_route_delete_prefix; straightforward header update.

Reviews (2): Last reviewed commit: "ospf6d: Remove ospf6 route when connecte..." | Re-trigger Greptile

Comment thread ospf6d/ospf6_zebra.c Outdated
Comment on lines +542 to +555
void ospf6_zebra_route_delete_prefix(struct ospf6_route *route, struct ospf6 *ospf6)
{
struct zapi_route api;

if (IS_OSPF6_DEBUG_ZEBRA(SEND))
zlog_debug("Send delete for route: %pFX a connected in Zebra now wins",
&route->prefix);

zapi_route_init(&api);
api.vrf_id = ospf6->vrf_id;
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = route->prefix;
zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Missing Graceful Restart guard

ospf6_zebra_route_delete_prefix sends a ZEBRA_ROUTE_DELETE to zebra without checking the GR state, while both ospf6_zebra_route_update_remove and ospf6_zebra_route_update_add explicitly bail out during graceful restart to preserve forwarding continuity. Deleting the OSPF6 route during GR would break the in-progress restart's forwarding plane state.

The same guard used by the other removal path should be applied here:

void ospf6_zebra_route_delete_prefix(struct ospf6_route *route, struct ospf6 *ospf6)
{
	struct zapi_route api;

	if (ospf6->gr_info.restart_in_progress
	    || ospf6->gr_info.prepare_in_progress) {
		if (IS_DEBUG_OSPF6_GR)
			zlog_debug(
				"Zebra: Graceful Restart in progress -- not deleting %pFX",
				&route->prefix);
		return;
	}

	if (IS_OSPF6_DEBUG_ZEBRA(SEND))
		zlog_debug("Send delete for route: %pFX a connected in Zebra now wins",
			   &route->prefix);

	zapi_route_init(&api);
	api.vrf_id = ospf6->vrf_id;
	api.type = ZEBRA_ROUTE_OSPF6;
	api.safi = SAFI_UNICAST;
	api.prefix = route->prefix;
	zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: ospf6d/ospf6_zebra.c
Line: 542-555

Comment:
**Missing Graceful Restart guard**

`ospf6_zebra_route_delete_prefix` sends a `ZEBRA_ROUTE_DELETE` to zebra without checking the GR state, while both `ospf6_zebra_route_update_remove` and `ospf6_zebra_route_update_add` explicitly bail out during graceful restart to preserve forwarding continuity. Deleting the OSPF6 route during GR would break the in-progress restart's forwarding plane state.

The same guard used by the other removal path should be applied here:

```c
void ospf6_zebra_route_delete_prefix(struct ospf6_route *route, struct ospf6 *ospf6)
{
	struct zapi_route api;

	if (ospf6->gr_info.restart_in_progress
	    || ospf6->gr_info.prepare_in_progress) {
		if (IS_DEBUG_OSPF6_GR)
			zlog_debug(
				"Zebra: Graceful Restart in progress -- not deleting %pFX",
				&route->prefix);
		return;
	}

	if (IS_OSPF6_DEBUG_ZEBRA(SEND))
		zlog_debug("Send delete for route: %pFX a connected in Zebra now wins",
			   &route->prefix);

	zapi_route_init(&api);
	api.vrf_id = ospf6->vrf_id;
	api.type = ZEBRA_ROUTE_OSPF6;
	api.safi = SAFI_UNICAST;
	api.prefix = route->prefix;
	zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);
}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not necessary to do this. The code is only removing the route if a ospf6 route was already installed. We cannot be in graceful restart situation if this is happening.

Comment thread ospf6d/ospf6_zebra.c Outdated
api.type = ZEBRA_ROUTE_OSPF6;
api.safi = SAFI_UNICAST;
api.prefix = route->prefix;
zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 zclient_route_send return value ignored

Every other direct zclient_route_send call in this file (e.g. in ospf6_zebra_route_update around line 499–507) checks the return code and calls flog_err on ZCLIENT_SEND_FAILURE. The new function silently drops any send error, making failures invisible in logs.

Suggested change
zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);
int ret = zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);
if (ret == ZCLIENT_SEND_FAILURE)
flog_err(EC_LIB_ZAPI_SOCKET,
"zclient_route_send() delete failed: %s",
safe_strerror(errno));
Prompt To Fix With AI
This is a comment left during a code review.
Path: ospf6d/ospf6_zebra.c
Line: 555

Comment:
**`zclient_route_send` return value ignored**

Every other direct `zclient_route_send` call in this file (e.g. in `ospf6_zebra_route_update` around line 499–507) checks the return code and calls `flog_err` on `ZCLIENT_SEND_FAILURE`. The new function silently drops any send error, making failures invisible in logs.

```suggestion
	int ret = zclient_route_send(ZEBRA_ROUTE_DELETE, ospf6_zclient, &api);

	if (ret == ZCLIENT_SEND_FAILURE)
		flog_err(EC_LIB_ZAPI_SOCKET,
			 "zclient_route_send() delete failed: %s",
			 safe_strerror(errno));
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable. change made

Currently when ospf6 installs a route that is later
covered by a connected, the ospf6 route is never removed.
Modify the code to detect the case where the new route
that `wins` in ospf6 notices that it is connected and the
old route that was in was a ospf6 route.  If so send a
specific route deletion for the ospf6 route.

This failure is happening infrequently in the ospf6_point_to_multipoint
test due to timing issues on how connected routes are received
into ospf6.

Signed-off-by: Donald Sharp <sharpd@nvidia.com>
@donaldsharp
donaldsharp force-pushed the ospf6_connected_wins branch from cfbdcf4 to 7acbf6d Compare April 8, 2026 16:44
@github-actions github-actions Bot added size/M and removed size/S labels Apr 8, 2026
@donaldsharp

Copy link
Copy Markdown
Member Author

@greptile review

@Jafaral

Jafaral commented Apr 8, 2026

Copy link
Copy Markdown
Member

@Mergifyio backport stable/10.6 stable/10.5

@Jafaral
Jafaral merged commit 4c5e5ee into FRRouting:master Apr 8, 2026
22 checks passed
@mergify

mergify Bot commented Apr 8, 2026

Copy link
Copy Markdown

backport stable/10.6 stable/10.5

βœ… Backports have been created

Details

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants