]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ospfd: blackhole route removal for area range
authorJR Rivers <jrrivers@cumulusnetworks.com>
Mon, 24 Sep 2012 17:26:46 +0000 (17:26 +0000)
committerDavid Lamparter <equinox@opensourcerouting.org>
Thu, 25 Oct 2012 17:15:58 +0000 (10:15 -0700)
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>
ospfd/ospf_abr.c
ospfd/ospf_route.c
ospfd/ospf_route.h

index b7cc20dd87bceb2aa807291f0a8ce0e2be5b76b7..ef1048b23b61513c02d528c2e2bb1e195a062bd7 100644 (file)
@@ -88,23 +88,18 @@ ospf_area_range_add (struct ospf_area *area, struct ospf_area_range *range)
 }
 
 static void
-ospf_area_range_delete (struct ospf_area *area, struct ospf_area_range *range)
+ospf_area_range_delete (struct ospf_area *area, struct route_node *rn)
 {
-  struct route_node *rn;
-  struct prefix_ipv4 p;
+  struct ospf_area_range *range = rn->info;
 
-  p.family = AF_INET;
-  p.prefixlen = range->masklen;
-  p.prefix = range->addr;
+  if (range->specifics != 0)
+    ospf_delete_discard_route (area->ospf->new_table,
+                              (struct prefix_ipv4 *) &rn->p);
 
-  rn = route_node_lookup (area->ranges, (struct prefix *)&p);
-  if (rn)
-    {
-      ospf_area_range_free (rn->info);
-      rn->info = NULL;
-      route_unlock_node (rn);
-      route_unlock_node (rn);
-    }
+  ospf_area_range_free (range);
+  rn->info = NULL;
+  route_unlock_node (rn);
+  route_unlock_node (rn);
 }
 
 struct ospf_area_range *
@@ -263,20 +258,20 @@ ospf_area_range_unset (struct ospf *ospf, struct in_addr area_id,
                       struct prefix_ipv4 *p)
 {
   struct ospf_area *area;
-  struct ospf_area_range *range;
+  struct route_node *rn;
 
   area = ospf_area_lookup_by_area_id (ospf, area_id);
   if (area == NULL)
     return 0;
 
-  range = ospf_area_range_lookup (area, p);
-  if (range == NULL)
+  rn = route_node_lookup (area->ranges, (struct prefix*)p);
+  if (rn == NULL)
     return 0;
 
-  if (ospf_area_range_active (range))
+  if (ospf_area_range_active (rn->info))
     ospf_schedule_abr_task (ospf);
 
-  ospf_area_range_delete (area, range);
+  ospf_area_range_delete (area, rn);
 
   return 1;
 }
@@ -1695,7 +1690,8 @@ ospf_abr_manage_discard_routes (struct ospf *ospf)
              ospf_add_discard_route (ospf->new_table, area,
                                      (struct prefix_ipv4 *) &rn->p);
            else
-             ospf_delete_discard_route ((struct prefix_ipv4 *) &rn->p);
+             ospf_delete_discard_route (ospf->new_table,
+                                        (struct prefix_ipv4 *) &rn->p);
          }
 }
 
index a5d6d18c9385361d957643421bb8151f44532865..c3acba348d01e1f3e9656cb8e75fbcf43ecca981 100644 (file)
@@ -954,6 +954,10 @@ ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
       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 @@ ospf_add_discard_route (struct route_table *rt, struct ospf_area *area,
 }
 
 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;
 }
 
index 5742b462c33710eb3dd3544361b08bb3f1231a82..6c202b0ccd3bdbba3bf00e3a2d64c4fe3dce7361 100644 (file)
@@ -159,7 +159,7 @@ extern void ospf_prune_unreachable_networks (struct route_table *);
 extern void ospf_prune_unreachable_routers (struct route_table *);
 extern int ospf_add_discard_route (struct route_table *, struct ospf_area *,
                                   struct prefix_ipv4 *);
-extern void ospf_delete_discard_route (struct prefix_ipv4 *);
+extern void ospf_delete_discard_route (struct route_table *, struct prefix_ipv4 *);
 extern int ospf_route_match_same (struct route_table *, struct prefix_ipv4 *,
                                  struct ospf_route *);