diff options
author | Donald Sharp <sharpd@nvidia.com> | 2024-10-14 17:25:32 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@nvidia.com> | 2024-10-14 17:27:53 +0200 |
commit | 74e25198e74c4066b630515d2971c3c9381d70f2 (patch) | |
tree | 4ca3a52f2a220b6964620b36e8cabce45bca9465 /zebra/connected.c | |
parent | build: FRR 10.3 development version (diff) | |
download | frr-74e25198e74c4066b630515d2971c3c9381d70f2.tar.xz frr-74e25198e74c4066b630515d2971c3c9381d70f2.zip |
zebra: Prevent a kernel route from being there when a connected should
There exists a series of events where a kernel route is learned
first( that happens to be exactly what a connected route should be )
and FRR ends up with both a kernel route and a connected route,
leaving us in a very strange spot. This code change just mirrors
the existing code of if there is a connected route drop the kernel
route. Here we just do the reverse, if we have a kernel route
already and a connected should be created, remove the kernel and
keep the connected.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
Diffstat (limited to 'zebra/connected.c')
-rw-r--r-- | zebra/connected.c | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/zebra/connected.c b/zebra/connected.c index 974a1c17a..ce26c14c0 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -176,6 +176,40 @@ static void connected_update(struct interface *ifp, struct connected *ifc) connected_announce(ifp, ifc); } +/* + * This function goes through and handles the deletion of a kernel route that happened + * to be the exact same as the connected route, so that the connected route wins. + * This can happen during processing if we happen to receive events in a slightly + * unexpected order. This is similiar to code in the other direction where if we + * have a kernel route don't install it if it perfectly matches a connected route. + */ +static void connected_remove_kernel_for_connected(afi_t afi, safi_t safi, struct zebra_vrf *zvrf, + struct prefix *p, struct nexthop *nh) +{ + struct route_node *rn; + struct route_entry *re; + rib_dest_t *dest; + struct route_table *table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf->vrf->vrf_id); + + rn = route_node_match(table, p); + if (!rn) + return; + + if (!prefix_same(&rn->p, p)) + return; + + dest = rib_dest_from_rnode(rn); + if (!dest || !dest->selected_fib) + return; + + re = dest->selected_fib; + if (re->type != ZEBRA_ROUTE_KERNEL) + return; + + rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_KERNEL, 0, 0, p, NULL, nh, 0, + zvrf->table_id, 0, 0, false); +} + /* Called from if_up(). */ void connected_up(struct interface *ifp, struct connected *ifc) { @@ -284,10 +318,13 @@ void connected_up(struct interface *ifp, struct connected *ifc) } if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) { + connected_remove_kernel_for_connected(afi, SAFI_UNICAST, zvrf, &p, &nh); + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0, false); + connected_remove_kernel_for_connected(afi, SAFI_MULTICAST, zvrf, &p, &nh); rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0, false); |