2003-06-19 "Suraev, Vadim" <vadim.suraev@terayon.com>

	* ospf_route.c: delete routes generated from AS-External routes if
	  there is a inter/intra route. Adds ospf_route_delete_same_ext()
	  which prunes external routes, which is called from
	  ospf_route_install() when new route table is installed.
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index 96f7531..0de415e 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -179,6 +179,39 @@
   return 0;
 }
 
+/* delete routes generated from AS-External routes if there is a inter/intra
+ * area route
+ */
+void 
+ospf_route_delete_same_ext(struct route_table *external_routes,
+                     struct route_table *routes)
+{
+  struct route_node *rn,
+                    *ext_rn;
+  
+  if ( (external_routes == NULL) || (routes == NULL) )
+    return;
+  
+  /* Remove deleted routes */
+  for ( rn = route_top (routes); rn; rn = route_next (rn) )
+    {
+      if (rn && rn->info)
+        {
+          struct prefix_ipv4 *p = &rn->p;
+          if ( (ext_rn = route_node_lookup (external_routes, p)) )
+            {
+              ospf_zebra_delete (p, ext_rn->info);
+              if (ext_rn->info)
+                {
+                  ospf_route_free( ext_rn->info);
+                  ext_rn->info = NULL;
+                }
+              route_unlock_node (ext_rn);
+            }
+        }
+    }
+}
+
 /* rt: Old, cmprt: New */
 void
 ospf_route_delete_uniq (struct route_table *rt, struct route_table *cmprt)
@@ -206,22 +239,24 @@
 
 /* Install routes to table. */
 void
-ospf_route_install (struct route_table *rt)
+ospf_route_install (struct ospf *ospf, struct route_table *rt)
 {
   struct route_node *rn;
   struct ospf_route *or;
 
   /* rt contains new routing table, new_table contains an old one.
      updating pointers */
-  if (ospf_top->old_table)
-    ospf_route_table_free (ospf_top->old_table);
- 
-  ospf_top->old_table = ospf_top->new_table;
-  ospf_top->new_table = rt;
+  if (ospf->old_table)
+    ospf_route_table_free (ospf->old_table);
+
+  ospf->old_table = ospf->new_table;
+  ospf->new_table = rt;
 
   /* Delete old routes. */
-  if (ospf_top->old_table)
-    ospf_route_delete_uniq (ospf_top->old_table, rt);
+  if (ospf->old_table)
+    ospf_route_delete_uniq (ospf->old_table, rt);
+  if (ospf->old_external_route)
+    ospf_route_delete_same_ext (ospf->old_external_route, rt);
 
   /* Install new routes. */
   for (rn = route_top (rt); rn; rn = route_next (rn))
@@ -229,12 +264,12 @@
       {
 	if (or->type == OSPF_DESTINATION_NETWORK)
 	  {
-	    if (! ospf_route_match_same (ospf_top->old_table,
+	    if (! ospf_route_match_same (ospf->old_table,
 					 (struct prefix_ipv4 *)&rn->p, or))
 	      ospf_zebra_add ((struct prefix_ipv4 *) &rn->p, or);
 	  }
 	else if (or->type == OSPF_DESTINATION_DISCARD)
-	  if (! ospf_route_match_same (ospf_top->old_table,
+	  if (! ospf_route_match_same (ospf->old_table,
 				       (struct prefix_ipv4 *) &rn->p, or))
 	    ospf_zebra_add_discard ((struct prefix_ipv4 *) &rn->p);
       }
@@ -595,7 +630,7 @@
       if (IS_DEBUG_OSPF_EVENT)
 	zlog_info ("ospf_intra_add_stub(): this network is on this router");
 
-      if ((oi = ospf_if_lookup_by_prefix (&p)))
+      if ((oi = ospf_if_lookup_by_prefix (area->ospf, &p)))
 	{
 	  if (IS_DEBUG_OSPF_EVENT)
 	    zlog_info ("ospf_intra_add_stub(): the interface is %s",
@@ -676,12 +711,15 @@
 void
 ospf_terminate ()
 {
-  if (ospf_top)
+  struct ospf *ospf;
+  listnode node;
+
+  LIST_LOOP (om->ospf, ospf, node)
     {
-      if (ospf_top->new_table)
-	ospf_route_delete (ospf_top->new_table);
-      if (ospf_top->old_external_route)
-	ospf_route_delete (ospf_top->old_external_route);
+      if (ospf->new_table)
+	ospf_route_delete (ospf->new_table);
+      if (ospf->old_external_route)
+	ospf_route_delete (ospf->old_external_route);
     }
 }
 
@@ -690,7 +728,8 @@
    o The other paths, intra-area backbone paths and inter-area paths,
      are of equal preference. */
 int
-ospf_asbr_route_cmp (struct ospf_route *r1, struct ospf_route *r2)
+ospf_asbr_route_cmp (struct ospf *ospf, struct ospf_route *r1,
+		     struct ospf_route *r2)
 {
   u_char r1_type, r2_type;
 
@@ -698,7 +737,7 @@
   r2_type = r2->path_type;
 
   /* If RFC1583Compat flag is on -- all paths are equal. */
-  if (CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+  if (CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
     return 0;
 
   /* r1/r2 itself is backbone, and it's Inter-area path. */
@@ -715,7 +754,8 @@
  ret == 0 -- r1 and r2 are the same.
  ret >  0 -- r2 is better. */
 int
-ospf_route_cmp (struct ospf_route *r1, struct ospf_route *r2)
+ospf_route_cmp (struct ospf *ospf, struct ospf_route *r1,
+		struct ospf_route *r2)
 {
   int ret = 0;
 
@@ -732,9 +772,9 @@
     case OSPF_PATH_INTER_AREA:
       break;
     case OSPF_PATH_TYPE1_EXTERNAL:
-      if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+      if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
 	{
-	  ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr);
+	  ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
 	  if (ret != 0)
 	    return ret;
 	}
@@ -743,9 +783,9 @@
       if ((ret = (r1->u.ext.type2_cost - r2->u.ext.type2_cost)))
 	return ret;
 
-      if (!CHECK_FLAG (ospf_top->config, OSPF_RFC1583_COMPATIBLE))
+      if (!CHECK_FLAG (ospf->config, OSPF_RFC1583_COMPATIBLE))
 	{
-	  ret = ospf_asbr_route_cmp (r1->u.ext.asbr, r2->u.ext.asbr);
+	  ret = ospf_asbr_route_cmp (ospf, r1->u.ext.asbr, r2->u.ext.asbr);
 	  if (ret != 0)
 	    return ret;
 	}