ospfd: blackhole route removal for area range
ISSUE
When an area range is created in which there the sub-area has routes that are
smaller than the range, an ABR creates a blackhole route to cover the range.
When the range is removed, the blackhole route is not removed.
--A----B----C---
B is an ABR with A in area 1 and C in area 0. If A advertises `10.2.0.0/30` and
`10.2.0.4/30` and B is configured with `area 0.0.0.1 range 10.2.0.0/29` a
blackhole is created on B (`blackhole 10.2.0.0/29 proto zebra`). When the
area/range is removed via the command line, the blackhole remains in existence
even though the "range" route is removed from area 0 and the individual routes
are propagated.
PATCH
The reason for this behavior is that, prior to this patch, the range is deleted
from the area's list, so when ospf_abr_manage_discard_routes() gets called,
there is nothing to clean up. The patch removes the discard route as part of
the processing of the command line (ospf_area_range_unset()).
Signed-off-by: JR Rivers <jrrivers@cumulusnetworks.com>
Signed-off-by: Scott Feldman <sfeldma@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index a5d6d18..c3acba3 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -954,6 +954,10 @@
ospf_route_free (rn->info);
}
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ospf_add_discard_route(): "
+ "adding %s/%d", inet_ntoa (p->prefix), p->prefixlen);
+
new_or = ospf_route_new ();
new_or->type = OSPF_DESTINATION_DISCARD;
new_or->id.s_addr = 0;
@@ -969,8 +973,52 @@
}
void
-ospf_delete_discard_route (struct prefix_ipv4 *p)
+ospf_delete_discard_route (struct route_table *rt, struct prefix_ipv4 *p)
{
+ struct route_node *rn;
+ struct ospf_route *or;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ospf_delete_discard_route(): "
+ "deleting %s/%d", inet_ntoa (p->prefix), p->prefixlen);
+
+ rn = route_node_lookup (rt, (struct prefix*)p);
+
+ if (rn == NULL)
+ {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("ospf_delete_discard_route(): no route found");
+ return;
+ }
+
+ or = rn->info;
+
+ if (or->path_type == OSPF_PATH_INTRA_AREA)
+ {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ospf_delete_discard_route(): "
+ "an intra-area route exists");
+ return;
+ }
+
+ if (or->type != OSPF_DESTINATION_DISCARD)
+ {
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug ("ospf_delete_discard_route(): "
+ "not a discard entry");
+ return;
+ }
+
+ /* free the route entry and the route node */
+ ospf_route_free (rn->info);
+
+ rn->info = NULL;
+ route_unlock_node (rn);
+ route_unlock_node (rn);
+
+ /* remove the discard entry from the rib */
ospf_zebra_delete_discard(p);
+
+ return;
}