Merge svn revisions 924 and 925 from Zebra CVS. Also remove useless
ospf6_lsdb prototype declaration from ospf6_lsa.h. Report sent to Yasuhiro
Ohara as well.
diff --git a/ospf6d/ChangeLog b/ospf6d/ChangeLog
index 52f4cef..43225bf 100644
--- a/ospf6d/ChangeLog
+++ b/ospf6d/ChangeLog
@@ -1,3 +1,8 @@
+2004-08-19  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
+
+	* ospf6_asbr.c: Bug in AS-External Origination fixed.
+	* ospf6d.h: version 0.9.7j
+
 2004-08-15  Yasuhiro Ohara  <yasu@sfc.wide.ad.jp>
 
 	* *.c: Area support almost done. (almost ! ;p)
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 397cef7..e9dc238 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -28,6 +28,7 @@
 #include "vty.h"
 #include "linklist.h"
 #include "command.h"
+#include "thread.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_route.h"
@@ -41,8 +42,9 @@
 #include "ospf6_interface.h"
 #include "ospf6_neighbor.h"
 
-#include "ospf6_abr.h"
 #include "ospf6_flood.h"
+#include "ospf6_intra.h"
+#include "ospf6_abr.h"
 #include "ospf6d.h"
 
 unsigned char conf_debug_ospf6_abr;
@@ -66,6 +68,80 @@
   return 0;
 }
 
+void
+ospf6_abr_enable_area (struct ospf6_area *area)
+{
+  struct ospf6_area *oa;
+  struct ospf6_route *ro;
+  listnode node;
+
+  for (node = listhead (area->ospf6->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+
+      /* update B bit for each area */
+      OSPF6_ROUTER_LSA_SCHEDULE (oa);
+
+      /* install other area's configured address range */
+      if (oa != area)
+        {
+          for (ro = ospf6_route_head (oa->range_table); ro;
+               ro = ospf6_route_next (ro))
+            ospf6_abr_originate_summary_to_area (ro, area);
+        }
+    }
+
+  /* install calculated routes to border routers */
+  for (ro = ospf6_route_head (area->ospf6->brouter_table); ro;
+       ro = ospf6_route_next (ro))
+    ospf6_abr_originate_summary_to_area (ro, area);
+
+  /* install calculated routes to network (may be rejected by ranges) */
+  for (ro = ospf6_route_head (area->ospf6->route_table); ro;
+       ro = ospf6_route_next (ro))
+    ospf6_abr_originate_summary_to_area (ro, area);
+}
+
+void
+ospf6_abr_disable_area (struct ospf6_area *area)
+{
+  struct ospf6_area *oa;
+  struct ospf6_route *ro;
+  struct ospf6_lsa *old;
+  listnode node;
+
+  /* Withdraw all summary prefixes previously originated */
+  for (ro = ospf6_route_head (area->summary_prefix); ro;
+       ro = ospf6_route_next (ro))
+    {
+      old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
+                               area->ospf6->router_id, area->lsdb);
+      if (old)
+        ospf6_lsa_purge (old);
+      ospf6_route_remove (ro, area->summary_prefix);
+    }
+
+  /* Withdraw all summary router-routes previously originated */
+  for (ro = ospf6_route_head (area->summary_router); ro;
+       ro = ospf6_route_next (ro))
+    {
+      old = ospf6_lsdb_lookup (ro->path.origin.type, ro->path.origin.id,
+                               area->ospf6->router_id, area->lsdb);
+      if (old)
+        ospf6_lsa_purge (old);
+      ospf6_route_remove (ro, area->summary_router);
+    }
+
+  /* Schedule Router-LSA for each area (ABR status may change) */
+  for (node = listhead (area->ospf6->area_list); node; nextnode (node))
+    {
+      oa = OSPF6_AREA (getdata (node));
+
+      /* update B bit for each area */
+      OSPF6_ROUTER_LSA_SCHEDULE (oa);
+    }
+}
+
 /* RFC 2328 12.4.3. Summary-LSAs */
 void
 ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
@@ -88,8 +164,7 @@
       char buf[64];
       if (route->type == OSPF6_DEST_TYPE_ROUTER)
         {
-          inet_ntop (AF_INET,
-                     &(ospf6_linkstate_prefix_adv_router (&route->prefix)),
+          inet_ntop (AF_INET, &(ADV_ROUTER_IN_PREFIX (&route->prefix)),
                      buf, sizeof (buf));
           zlog_info ("Originating summary in area %s for ASBR %s",
                      area->name, buf);
@@ -314,8 +389,7 @@
       router_lsa->options[1] = route->path.options[1];
       router_lsa->options[2] = route->path.options[2];
       OSPF6_ABR_SUMMARY_METRIC_SET (router_lsa, route->path.cost);
-      router_lsa->router_id =
-        ospf6_linkstate_prefix_adv_router (&route->prefix);
+      router_lsa->router_id = ADV_ROUTER_IN_PREFIX (&route->prefix);
       type = htons (OSPF6_LSTYPE_INTER_ROUTER);
     }
   else
@@ -426,6 +500,9 @@
   u_int32_t cost = 0;
   int i;
 
+  if (IS_OSPF6_DEBUG_ABR)
+    zlog_info ("Examin %s in area %s", lsa->name, oa->name);
+
   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
       struct ospf6_inter_prefix_lsa *prefix_lsa;
@@ -467,8 +544,18 @@
     }
 
   /* (1) if cost == LSInfinity or if the LSA is MaxAge */
-  if (cost == LS_INFINITY || OSPF6_LSA_IS_MAXAGE (lsa))
+  if (cost == LS_INFINITY)
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("cost is LS_INFINITY, ignore");
+      if (old)
+        ospf6_route_remove (old, oa->ospf6->route_table);
+      return;
+    }
+  if (OSPF6_LSA_IS_MAXAGE (lsa))
+    {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("LSA is MaxAge, ignore");
       if (old)
         ospf6_route_remove (old, oa->ospf6->route_table);
       return;
@@ -477,6 +564,8 @@
   /* (2) if the LSA is self-originated, ignore */
   if (lsa->header->adv_router == oa->ospf6->router_id)
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("LSA is self-originated, ignore");
       if (old)
         ospf6_route_remove (old, oa->ospf6->route_table);
       return;
@@ -488,6 +577,8 @@
       range = ospf6_route_lookup (&prefix, oa->range_table);
       if (range)
         {
+          if (IS_OSPF6_DEBUG_ABR)
+            zlog_info ("Prefix is equal to address range, ignore");
           if (old)
             ospf6_route_remove (old, oa->ospf6->route_table);
           return;
@@ -500,6 +591,8 @@
   if (abr_entry == NULL || abr_entry->path.area_id != oa->area_id ||
       ! CHECK_FLAG (abr_entry->path.router_bits, OSPF6_ROUTER_BIT_B))
     {
+      if (IS_OSPF6_DEBUG_ABR)
+        zlog_info ("ABR router entry does not exist, ignore");
       if (old)
         ospf6_route_remove (old, oa->ospf6->route_table);
       return;
@@ -528,6 +621,8 @@
   for (i = 0; i < OSPF6_MULTI_PATH_LIMIT; i++)
     route->nexthop[i] = abr_entry->nexthop[i];
 
+  if (IS_OSPF6_DEBUG_ABR)
+    zlog_info ("Install route");
   ospf6_route_add (route, table);
 }
 
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index a12d985..3257c73 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -54,6 +54,9 @@
 
 int ospf6_is_router_abr (struct ospf6 *o);
 
+void ospf6_abr_enable_area (struct ospf6_area *oa);
+void ospf6_abr_disable_area (struct ospf6_area *oa);
+
 void ospf6_abr_originate_summary_to_area (struct ospf6_route *route,
                                           struct ospf6_area *area);
 void ospf6_abr_originate_summary (struct ospf6_route *route);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index a8a1ce1..7884a6b 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -523,6 +523,7 @@
           zlog_info ("Advertise as AS-External Id:%s", ibuf);
         }
 
+      match->path.origin.id = htonl (info->id);
       ospf6_as_external_lsa_originate (match);
       return;
     }
@@ -571,6 +572,7 @@
       zlog_info ("Advertise as AS-External Id:%s", ibuf);
     }
 
+  route->path.origin.id = htonl (info->id);
   ospf6_as_external_lsa_originate (route);
 
   /* Router-Bit (ASBR Flag) may have to be updated */
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index aeff15b..0511202 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -204,6 +204,7 @@
 ospf6_install_lsa (struct ospf6_lsa *lsa)
 {
   struct ospf6_lsa *old;
+  struct timeval now;
 
   if (IS_OSPF6_DEBUG_LSA (RECV) || IS_OSPF6_DEBUG_LSA (DATABASE))
     zlog_info ("Install LSA: %s", lsa->name);
@@ -213,10 +214,20 @@
   old = ospf6_lsdb_lookup (lsa->header->type, lsa->header->id,
                            lsa->header->adv_router, lsa->lsdb);
   if (old)
-    ospf6_flood_clear (old);
+    {
+      THREAD_OFF (old->expire);
+      ospf6_flood_clear (old);
+    }
+
+  gettimeofday (&now, (struct timezone *) NULL);
+  if (ospf6_lsa_age_current (lsa) != MAXAGE)
+    lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
+                                    MAXAGE + lsa->birth.tv_sec - now.tv_sec);
+  else
+    lsa->expire = NULL;
 
   /* actually install */
-  gettimeofday (&lsa->installed, (struct timezone *) NULL);
+  lsa->installed = now;
   ospf6_lsdb_add (lsa, lsa->lsdb);
 
   return;
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 56ecacc..965debb 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1608,7 +1608,7 @@
        "Debug OSPFv3 Interface\n"
       )
 {
-  OSPF6_DEBUG_INTERFACE_ON ();
+  OSPF6_DEBUG_INTERFACE_OFF ();
   return CMD_SUCCESS;
 }
 
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index c031a2d..8eea002 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -109,7 +109,7 @@
 }
 
 /* ospf6 age functions */
-/* calculate birth and set expire timer */
+/* calculate birth */
 static void
 ospf6_lsa_age_set (struct ospf6_lsa *lsa)
 {
@@ -123,11 +123,7 @@
 
   lsa->birth.tv_sec = now.tv_sec - ntohs (lsa->header->age);
   lsa->birth.tv_usec = now.tv_usec;
-  if (ntohs (lsa->header->age) != MAXAGE)
-    lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
-                                    MAXAGE + lsa->birth.tv_sec - now.tv_sec);
-  else
-    lsa->expire = NULL;
+
   return;
 }
 
@@ -421,7 +417,7 @@
   /* dump string */
   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
 
-  /* calculate birth, expire and refresh of this lsa */
+  /* calculate birth of this lsa */
   ospf6_lsa_age_set (lsa);
 
   if (IS_OSPF6_DEBUG_LSA (MEMORY))
@@ -456,7 +452,7 @@
   /* dump string */
   ospf6_lsa_printbuf (lsa, lsa->name, sizeof (lsa->name));
 
-  /* calculate birth, expire and refresh of this lsa */
+  /* calculate birth of this lsa */
   ospf6_lsa_age_set (lsa);
 
   if (IS_OSPF6_DEBUG_LSA (MEMORY))
@@ -500,6 +496,7 @@
     copy = ospf6_lsa_create (lsa->header);
   assert (copy->lock == 0);
 
+  copy->birth = lsa->birth;
   copy->installed = lsa->installed;
   copy->originated = lsa->originated;
   copy->lsdb = lsa->lsdb;
@@ -559,7 +556,7 @@
   /* reinstall lsa */
   if (IS_OSPF6_DEBUG_LSA (DATABASE))
     zlog_info ("Reinstall MaxAge %s", lsa->name);
-  ospf6_lsdb_add (lsa, lsa->lsdb);
+  ospf6_install_lsa (lsa);
 
   /* schedule maxage remover */
   ospf6_maxage_remove (ospf6);
@@ -584,6 +581,8 @@
                             old->header->adv_router, lsdb_self);
   if (self == NULL)
     {
+      if (IS_OSPF6_DEBUG_LSA (ORIGINATE))
+        zlog_info ("Refresh: could not find self LSA, flush %s", old->name);
       ospf6_lsa_premature_aging (old);
       return 0;
     }
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index 54921e1..961f11e 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -121,7 +121,6 @@
 
   int               retrans_count;
 
-struct ospf6_lsdb;
   struct ospf6_lsdb *lsdb;
 
   /* lsa instance */
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 9b37406..247238b 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -83,15 +83,14 @@
   if (num == lsdb->count)
     return;
 
-  if (IS_OSPF6_DEBUG_LSA (DATABASE))
-    {
-      zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
-                 lsdb, lsdb->count, num);
-      for (debug = ospf6_lsdb_head (lsdb); debug;
-           debug = ospf6_lsdb_next (debug))
-        zlog_info ("%p %p %s", debug->prev, debug->next, debug->name);
-      zlog_info ("DUMP END");
-    }
+  zlog_info ("PANIC !! lsdb[%p]->count = %d, real = %d",
+             lsdb, lsdb->count, num);
+  for (debug = ospf6_lsdb_head (lsdb); debug;
+       debug = ospf6_lsdb_next (debug))
+    zlog_info ("%p %p %s lsdb[%p]", debug->prev, debug->next, debug->name,
+               debug->lsdb);
+  zlog_info ("DUMP END");
+
   assert (num == lsdb->count);
 }
 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index 333b2ce..069502f 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -215,6 +215,11 @@
 #define ospf6_linkstate_prefix_id(x) \
   (*(u_int32_t *)(&(x)->u.prefix6.s6_addr[4]))
 
+#define ID_IN_PREFIX(x) \
+  (*(u_int32_t *)(&(x)->u.prefix6.s6_addr[0]))
+#define ADV_ROUTER_IN_PREFIX(x) \
+  (*(u_int32_t *)(&(x)->u.prefix6.s6_addr[4]))
+
 /* Function prototype */
 void ospf6_linkstate_prefix (u_int32_t adv_router, u_int32_t id,
                              struct prefix *prefix);
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index d3c0f81..63bc10a 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -151,7 +151,7 @@
 
   lsa = ospf6_lsdb_lookup (type, id, adv_router, v->area->lsdb);
 
-  if (IS_OSPF6_DEBUG_SPF (DETAIL))
+  if (IS_OSPF6_DEBUG_SPF (PROCESS))
     {
       char ibuf[16], abuf[16];
       inet_ntop (AF_INET, &id, ibuf, sizeof (ibuf));
@@ -212,7 +212,7 @@
         }
     }
 
-  if (IS_OSPF6_DEBUG_SPF (DETAIL))
+  if (IS_OSPF6_DEBUG_SPF (PROCESS))
     zlog_info ("  Backlink %s", (found ? "OK" : "FAIL"));
 
   return found;
@@ -236,7 +236,7 @@
   oi = ospf6_interface_lookup_by_ifindex (ifindex);
   if (oi == NULL)
     {
-      if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
         zlog_warn ("Can't find interface in SPF: ifindex %d", ifindex);
       return;
     }
@@ -255,7 +255,7 @@
         continue;
 
       link_lsa = (struct ospf6_link_lsa *) OSPF6_LSA_HEADER_END (lsa->header);
-      if (IS_OSPF6_DEBUG_SPF (DETAIL))
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
         {
           inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, sizeof (buf));
           zlog_info ("  nexthop %s from %s", buf, lsa->name);
@@ -270,7 +270,7 @@
         }
     }
 
-  if (i == 0 && IS_OSPF6_DEBUG_SPF (SUMMARY))
+  if (i == 0 && IS_OSPF6_DEBUG_SPF (PROCESS))
     zlog_info ("No nexthop for %s found", w->name);
 }
 
@@ -283,14 +283,14 @@
   struct ospf6_vertex *prev, *w;
   listnode node;
 
-  if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+  if (IS_OSPF6_DEBUG_SPF (PROCESS))
     zlog_info ("SPF install %s hops %d cost %d",
                v->name, v->hops, v->cost);
 
   route = ospf6_route_lookup (&v->vertex_id, result_table);
   if (route && route->path.cost < v->cost)
     {
-      if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
         zlog_info ("  already installed with lower cost (%d), ignore",
                    route->path.cost);
       ospf6_vertex_delete (v);
@@ -298,7 +298,7 @@
     }
   else if (route && route->path.cost == v->cost)
     {
-      if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
         zlog_info ("  another path found, merge");
 
       for (i = 0; ospf6_nexthop_is_set (&v->nexthop[i]) &&
@@ -477,7 +477,7 @@
             }
 
           /* add new candidate to the candidate_list */
-          if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+          if (IS_OSPF6_DEBUG_SPF (PROCESS))
             zlog_info ("  New candidate: %s hops %d cost %d",
                        w->name, w->hops, w->cost);
           pqueue_enqueue (w, candidate_list);
@@ -496,7 +496,7 @@
   oa = (struct ospf6_area *) THREAD_ARG (t);
   oa->thread_spf_calculation = NULL;
 
-  if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+  if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
     zlog_info ("SPF calculation for area %s", oa->name);
 
   /* execute SPF calculation */
@@ -504,7 +504,7 @@
   ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
   gettimeofday (&end, (struct timezone *) NULL);
 
-  if (IS_OSPF6_DEBUG_SPF (SUMMARY))
+  if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
     {
       timersub (&end, &start, &runtime);
       zlog_info ("SPF calculation for area %s: runtime %ld sec %ld usec",
@@ -558,62 +558,64 @@
   free (next_prefix);
 }
 
-DEFUN (debug_ospf6_spf_detail,
-       debug_ospf6_spf_detail_cmd,
-       "debug ospf6 spf detail",
+DEFUN (debug_ospf6_spf_process,
+       debug_ospf6_spf_process_cmd,
+       "debug ospf6 spf process",
        DEBUG_STR
        OSPF6_STR
        "Debug SPF Calculation\n"
-       "Debug Detailed SPF\n"
+       "Debug Detailed SPF Process\n"
       )
 {
   unsigned char level = 0;
-  level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
+  level = OSPF6_DEBUG_SPF_PROCESS;
   OSPF6_DEBUG_SPF_ON (level);
   return CMD_SUCCESS;
 }
 
-DEFUN (debug_ospf6_spf,
-       debug_ospf6_spf_cmd,
-       "debug ospf6 spf",
+DEFUN (debug_ospf6_spf_time,
+       debug_ospf6_spf_time_cmd,
+       "debug ospf6 spf time",
        DEBUG_STR
        OSPF6_STR
        "Debug SPF Calculation\n"
+       "Measure time taken by SPF Calculation\n"
       )
 {
   unsigned char level = 0;
-  level = OSPF6_DEBUG_SPF_SUMMARY;
+  level = OSPF6_DEBUG_SPF_TIME;
   OSPF6_DEBUG_SPF_ON (level);
   return CMD_SUCCESS;
 }
 
-DEFUN (no_debug_ospf6_spf_detail,
-       no_debug_ospf6_spf_detail_cmd,
-       "no debug ospf6 spf detail",
+DEFUN (no_debug_ospf6_spf_process,
+       no_debug_ospf6_spf_process_cmd,
+       "no debug ospf6 spf process",
        NO_STR
        DEBUG_STR
        OSPF6_STR
        "Quit Debugging SPF Calculation\n"
-       "Quit Debugging Detailed SPF (change to debug summary)\n"
+       "Quit Debugging Detailed SPF Process\n"
       )
 {
   unsigned char level = 0;
-  level = OSPF6_DEBUG_SPF_DETAIL;
+  level = OSPF6_DEBUG_SPF_PROCESS;
   OSPF6_DEBUG_SPF_OFF (level);
   return CMD_SUCCESS;
 }
 
-DEFUN (no_debug_ospf6_spf,
-       no_debug_ospf6_spf_cmd,
-       "no debug ospf6 spf",
+DEFUN (no_debug_ospf6_spf_time,
+       no_debug_ospf6_spf_time_cmd,
+       "no debug ospf6 spf time",
        NO_STR
        DEBUG_STR
        OSPF6_STR
        "Quit Debugging SPF Calculation\n"
+       "Quit Measuring time taken by SPF Calculation\n"
       )
 {
   unsigned char level = 0;
-  level = OSPF6_DEBUG_SPF_SUMMARY | OSPF6_DEBUG_SPF_DETAIL;
+  level = OSPF6_DEBUG_SPF_TIME;
   OSPF6_DEBUG_SPF_OFF (level);
   return CMD_SUCCESS;
 }
@@ -621,24 +623,24 @@
 int
 config_write_ospf6_debug_spf (struct vty *vty)
 {
-  if (IS_OSPF6_DEBUG_SPF (DETAIL))
-    vty_out (vty, "debug ospf6 spf detail%s", VNL);
-  else if (IS_OSPF6_DEBUG_SPF (SUMMARY))
-    vty_out (vty, "debug ospf6 spf%s", VNL);
+  if (IS_OSPF6_DEBUG_SPF (PROCESS))
+    vty_out (vty, "debug ospf6 spf process%s", VNL);
+  if (IS_OSPF6_DEBUG_SPF (TIME))
+    vty_out (vty, "debug ospf6 spf time%s", VNL);
   return 0;
 }
 
 void
 install_element_ospf6_debug_spf ()
 {
-  install_element (ENABLE_NODE, &debug_ospf6_spf_cmd);
-  install_element (ENABLE_NODE, &debug_ospf6_spf_detail_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_spf_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_spf_detail_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_spf_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_spf_detail_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_spf_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_spf_detail_cmd);
+  install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
+  install_element (ENABLE_NODE, &debug_ospf6_spf_time_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf6_spf_process_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf6_spf_time_cmd);
+  install_element (CONFIG_NODE, &debug_ospf6_spf_process_cmd);
+  install_element (CONFIG_NODE, &debug_ospf6_spf_time_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf6_spf_process_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf6_spf_time_cmd);
 }
 
 void
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index 1c04afb..64f5ed8 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -24,8 +24,8 @@
 
 /* Debug option */
 extern unsigned char conf_debug_ospf6_spf;
-#define OSPF6_DEBUG_SPF_SUMMARY   0x01
-#define OSPF6_DEBUG_SPF_DETAIL    0x02
+#define OSPF6_DEBUG_SPF_PROCESS   0x01
+#define OSPF6_DEBUG_SPF_TIME      0x02
 #define OSPF6_DEBUG_SPF_ON(level) \
   (conf_debug_ospf6_spf |= (level))
 #define OSPF6_DEBUG_SPF_OFF(level) \
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index 865a116..5710316 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -335,12 +335,10 @@
       )
 {
   struct ospf6 *o;
-  struct ospf6_area *oa, *area;
+  struct ospf6_area *oa;
   struct ospf6_interface *oi;
   struct interface *ifp;
   u_int32_t area_id;
-  listnode node;
-  struct ospf6_route *ro;
 
   o = (struct ospf6 *) vty->index;
 
@@ -377,25 +375,9 @@
   /* start up */
   thread_add_event (master, interface_up, oi, 0);
 
-  /* ABR stuff, redistribute inter-area LSAs and
-     re-originate Router-LSA (B-bit may have been changed) */
-  for (node = listhead (o->area_list); node; nextnode (node))
-    {
-      area = OSPF6_AREA (getdata (node));
-      OSPF6_ROUTER_LSA_SCHEDULE (area);
-
-      for (ro = ospf6_route_head (area->range_table); ro;
-           ro = ospf6_route_next (ro))
-        ospf6_abr_originate_summary_to_area (ro, oa);
-    }
-
-  for (ro = ospf6_route_head (o->brouter_table); ro;
-       ro = ospf6_route_next (ro))
-    ospf6_abr_originate_summary_to_area (ro, oa);
-
-  for (ro = ospf6_route_head (o->route_table); ro;
-       ro = ospf6_route_next (ro))
-    ospf6_abr_originate_summary_to_area (ro, oa);
+  /* If the router is ABR, originate summary routes */
+  if (ospf6_is_router_abr (o))
+    ospf6_abr_enable_area (oa);
 
   return CMD_SUCCESS;
 }
@@ -412,12 +394,9 @@
 {
   struct ospf6 *o;
   struct ospf6_interface *oi;
-  struct ospf6_area *oa, *area;
+  struct ospf6_area *oa;
   struct interface *ifp;
   u_int32_t area_id;
-  listnode node;
-  struct ospf6_route *ro;
-  struct ospf6_lsa *old;
 
   o = (struct ospf6 *) vty->index;
 
@@ -459,35 +438,7 @@
   if (oa->if_list->count == 0)
     {
       UNSET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
-
-      for (ro = ospf6_route_head (oa->summary_prefix); ro;
-           ro = ospf6_route_next (ro))
-        {
-          old = ospf6_lsdb_lookup (ro->path.origin.type,
-                                   ro->path.origin.id,
-                                   oa->ospf6->router_id, oa->lsdb);
-          if (old)
-            ospf6_lsa_purge (old);
-          ospf6_route_remove (ro, oa->summary_prefix);
-        }
-      for (ro = ospf6_route_head (oa->summary_router); ro;
-           ro = ospf6_route_next (ro))
-        {
-          old = ospf6_lsdb_lookup (ro->path.origin.type,
-                                   ro->path.origin.id,
-                                   oa->ospf6->router_id, oa->lsdb);
-          if (old)
-            ospf6_lsa_purge (old);
-          ospf6_route_remove (ro, oa->summary_router);
-        }
-    }
-
-  /* Schedule Refreshment of Router-LSA for each area
-     (ABR status may change) */
-  for (node = listhead (o->area_list); node; nextnode (node))
-    {
-      area = OSPF6_AREA (getdata (node));
-      OSPF6_ROUTER_LSA_SCHEDULE (area);
+      ospf6_abr_disable_area (oa);
     }
 
   return CMD_SUCCESS;
diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c
index 6cc0764..28e6b94 100644
--- a/ospf6d/ospf6d.c
+++ b/ospf6d/ospf6d.c
@@ -50,92 +50,29 @@
 {
 }
 
-static struct route_node *
-_route_next_until (struct route_node *node, struct route_node *limit)
-{
-  struct route_node *next;
-  struct route_node *start;
-
-  /* Node may be deleted from route_unlock_node so we have to preserve
-     next node's pointer. */
-
-  if (node->l_left)
-    {
-      next = node->l_left;
-      if (next == limit)
-        {
-          route_unlock_node (node);
-          return NULL;
-        }
-      route_lock_node (next);
-      route_unlock_node (node);
-      return next;
-    }
-  if (node->l_right)
-    {
-      next = node->l_right;
-      if (next == limit)
-        {
-          route_unlock_node (node);
-          return NULL;
-        }
-      route_lock_node (next);
-      route_unlock_node (node);
-      return next;
-    }
-
-  start = node;
-  while (node->parent)
-    {
-      if (node->parent->l_left == node && node->parent->l_right)
-	{
-	  next = node->parent->l_right;
-          if (next == limit)
-            {
-              route_unlock_node (start);
-              return NULL;
-            }
-	  route_lock_node (next);
-	  route_unlock_node (start);
-	  return next;
-	}
-      node = node->parent;
-    }
-
-  route_unlock_node (start);
-  return NULL;
-}
-
 struct route_node *
 route_prev (struct route_node *node)
 {
   struct route_node *end;
   struct route_node *prev = NULL;
 
-  if (node->parent == NULL)
-    {
-      route_unlock_node (node);
-      return NULL;
-    }
-
-  if (node->parent->l_left == node)
-    {
-      prev = node->parent;
-      route_lock_node (prev);
-      route_unlock_node (node);
-      return prev;
-    }
-
   end = node;
   node = node->parent;
-  route_lock_node (node);
+  if (node)
+    route_lock_node (node);
   while (node)
     {
       prev = node;
-      node = _route_next_until (node, end);
+      node = route_next (node);
+      if (node == end)
+        {
+          route_unlock_node (node);
+          node = NULL;
+        }
     }
   route_unlock_node (end);
-  route_lock_node (prev);
+  if (prev)
+    route_lock_node (prev);
 
   return prev;
 }
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index 3274242..1b68a0f 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -22,7 +22,7 @@
 #ifndef OSPF6D_H
 #define OSPF6D_H
 
-#define OSPF6_DAEMON_VERSION    "0.9.7i"
+#define OSPF6_DAEMON_VERSION    "0.9.7j"
 
 /* global variables */
 extern int errno;