Merge volatile/cumulus_ospf6d

Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
diff --git a/doc/ospf6d.texi b/doc/ospf6d.texi
index 6667221..d981820 100644
--- a/doc/ospf6d.texi
+++ b/doc/ospf6d.texi
@@ -28,6 +28,44 @@
 be specified as 0.
 @end deffn
 
+@deffn {OSPF6 Command} {timers throttle spf @var{delay} @var{initial-holdtime} @var{max-holdtime}} {}
+@deffnx {OSPF6 Command} {no timers throttle spf} {}
+This command sets the initial @var{delay}, the @var{initial-holdtime}
+and the @var{maximum-holdtime} between when SPF is calculated and the
+event which triggered the calculation. The times are specified in
+milliseconds and must be in the range of 0 to 600000 milliseconds.
+
+The @var{delay} specifies the minimum amount of time to delay SPF
+calculation (hence it affects how long SPF calculation is delayed after
+an event which occurs outside of the holdtime of any previous SPF
+calculation, and also serves as a minimum holdtime).
+
+Consecutive SPF calculations will always be seperated by at least
+'hold-time' milliseconds. The hold-time is adaptive and initially is
+set to the @var{initial-holdtime} configured with the above command.
+Events which occur within the holdtime of the previous SPF calculation
+will cause the holdtime to be increased by @var{initial-holdtime}, bounded
+by the @var{maximum-holdtime} configured with this command. If the adaptive
+hold-time elapses without any SPF-triggering event occuring then
+the current holdtime is reset to the @var{initial-holdtime}.
+
+@example
+@group
+router ospf6
+ timers throttle spf 200 400 10000
+@end group
+@end example
+
+In this example, the @var{delay} is set to 200ms, the @var{initial
+holdtime} is set to 400ms and the @var{maximum holdtime} to 10s. Hence
+there will always be at least 200ms between an event which requires SPF
+calculation and the actual SPF calculation. Further consecutive SPF
+calculations will always be seperated by between 400ms to 10s, the
+hold-time increasing by 400ms each time an SPF-triggering event occurs
+within the hold-time of the previous SPF calculation.
+
+@end deffn
+
 @node OSPF6 area
 @section OSPF6 area
 
@@ -60,6 +98,10 @@
 Sets interface's Inf-Trans-Delay.  Default value is 1.
 @end deffn
 
+@deffn {Interface Command} {ipv6 ospf6 network (broadcast|point-to-point)} {}
+Set explicitly network type for specifed interface.
+@end deffn
+
 @node Redistribute routes to OSPF6
 @section Redistribute routes to OSPF6
 
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 44d95bb..bd21092 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -27,7 +27,7 @@
 	str.h stream.h table.h thread.h vector.h version.h vty.h zebra.h \
 	plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \
 	privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \
-	workqueue.h route_types.h
+	workqueue.h route_types.h libospf.h
 
 EXTRA_DIST = \
 	regex.c regex-gnu.h \
diff --git a/lib/if.c b/lib/if.c
index e26aa04..6348403 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -304,6 +304,30 @@
   return match;
 }
 
+/* Lookup interface by prefix */
+struct interface *
+if_lookup_prefix (struct prefix *prefix)
+{
+  struct listnode *node;
+  struct prefix addr;
+  int bestlen = 0;
+  struct listnode *cnode;
+  struct interface *ifp;
+  struct connected *c;
+
+  for (ALL_LIST_ELEMENTS_RO (iflist, node, ifp))
+    {
+      for (ALL_LIST_ELEMENTS_RO (ifp->connected, cnode, c))
+        {
+          if (prefix_cmp(c->address, prefix) == 0)
+            {
+              return ifp;
+            }
+        }
+    }
+  return NULL;
+}
+
 /* Get interface by name if given name interface doesn't exist create
    one. */
 struct interface *
diff --git a/lib/if.h b/lib/if.h
index 13cc254..8081be8 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -245,6 +245,7 @@
 extern struct interface *if_lookup_by_index (unsigned int);
 extern struct interface *if_lookup_exact_address (struct in_addr);
 extern struct interface *if_lookup_address (struct in_addr);
+extern struct interface *if_lookup_prefix (struct prefix *prefix);
 
 /* These 2 functions are to be used when the ifname argument is terminated
    by a '\0' character: */
diff --git a/lib/libospf.h b/lib/libospf.h
new file mode 100644
index 0000000..856c76d
--- /dev/null
+++ b/lib/libospf.h
@@ -0,0 +1,92 @@
+/*
+ * Defines and structures common to OSPFv2 and OSPFv3
+ * Copyright (C) 1998, 99, 2000 Kunihiro Ishiguro, Toshiaki Takada
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Zebra; see the file COPYING.  If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _LIBOSPFD_H
+#define _LIBOSPFD_H
+
+/* IP precedence. */
+#ifndef IPTOS_PREC_INTERNETCONTROL
+#define IPTOS_PREC_INTERNETCONTROL	0xC0
+#endif /* IPTOS_PREC_INTERNETCONTROL */
+
+/* Default protocol, port number. */
+#ifndef IPPROTO_OSPFIGP
+#define IPPROTO_OSPFIGP         89
+#endif /* IPPROTO_OSPFIGP */
+
+/* Architectual Constants */
+#ifdef DEBUG
+#define OSPF_LS_REFRESH_TIME                    60
+#else
+#define OSPF_LS_REFRESH_TIME                  1800
+#endif
+#define OSPF_MIN_LS_INTERVAL                     5
+#define OSPF_MIN_LS_ARRIVAL                      1
+#define OSPF_LSA_INITIAL_AGE                     0	/* useful for debug */
+#define OSPF_LSA_MAXAGE                       3600
+#define OSPF_CHECK_AGE                         300
+#define OSPF_LSA_MAXAGE_DIFF                   900
+#define OSPF_LS_INFINITY                  0xffffff
+#define OSPF_DEFAULT_DESTINATION        0x00000000      /* 0.0.0.0 */
+#define OSPF_INITIAL_SEQUENCE_NUMBER    0x80000001
+#define OSPF_MAX_SEQUENCE_NUMBER        0x7fffffff
+
+/* OSPF Interface Types */
+#define OSPF_IFTYPE_NONE		0
+#define OSPF_IFTYPE_POINTOPOINT		1
+#define OSPF_IFTYPE_BROADCAST		2
+#define OSPF_IFTYPE_NBMA		3
+#define OSPF_IFTYPE_POINTOMULTIPOINT	4
+#define OSPF_IFTYPE_VIRTUALLINK		5
+#define OSPF_IFTYPE_LOOPBACK            6
+#define OSPF_IFTYPE_MAX			7
+
+/* OSPF interface default values. */
+#define OSPF_OUTPUT_COST_DEFAULT           10
+#define OSPF_OUTPUT_COST_INFINITE	   UINT16_MAX
+#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT  40
+#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL   1
+#define OSPF_HELLO_INTERVAL_DEFAULT        10
+#define OSPF_ROUTER_PRIORITY_DEFAULT        1
+#define OSPF_RETRANSMIT_INTERVAL_DEFAULT    5
+#define OSPF_TRANSMIT_DELAY_DEFAULT         1
+#define OSPF_DEFAULT_BANDWIDTH		 10000	/* Kbps */
+
+#define OSPF_DEFAULT_REF_BANDWIDTH	100000  /* Kbps */
+
+#define OSPF_POLL_INTERVAL_DEFAULT         60
+#define OSPF_NEIGHBOR_PRIORITY_DEFAULT      0
+
+#define OSPF_MTU_IGNORE_DEFAULT             0
+#define OSPF_FAST_HELLO_DEFAULT             0
+
+#define OSPF_AREA_BACKBONE              0x00000000      /* 0.0.0.0 */
+
+/* SPF Throttling timer values. */
+#define OSPF_SPF_DELAY_DEFAULT              200
+#define OSPF_SPF_HOLDTIME_DEFAULT           1000
+#define OSPF_SPF_MAX_HOLDTIME_DEFAULT	    10000
+
+#define OSPF_LSA_MAXAGE_CHECK_INTERVAL		30
+#define OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT	60
+
+#endif /* _LIBOSPFD_H */
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index c3a63fe..54404ab 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -253,7 +253,7 @@
     }
 
   /* do not generate if the route cost is greater or equal to LSInfinity */
-  if (route->path.cost >= LS_INFINITY)
+  if (route->path.cost >= OSPF_LS_INFINITY)
     {
       if (is_debug)
         zlog_debug ("The cost exceeds LSInfinity, withdraw");
@@ -296,7 +296,7 @@
       /* ranges are ignored when originate backbone routes to transit area.
          Otherwise, if ranges are configured, the route is suppressed. */
       if (range && ! CHECK_FLAG (range->flag, OSPF6_ROUTE_REMOVE) &&
-          (route->path.area_id != BACKBONE_AREA_ID ||
+          (route->path.area_id != OSPF_AREA_BACKBONE ||
            ! IS_AREA_TRANSIT (area)))
         {
           if (is_debug)
@@ -537,13 +537,13 @@
   int i;
   char buf[64];
   int is_debug = 0;
+  struct ospf6_inter_prefix_lsa *prefix_lsa = NULL;
+  struct ospf6_inter_router_lsa *router_lsa = NULL;
 
   memset (&prefix, 0, sizeof (prefix));
 
   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
-      struct ospf6_inter_prefix_lsa *prefix_lsa;
-
       if (IS_OSPF6_DEBUG_EXAMIN (INTER_PREFIX))
         {
           is_debug++;
@@ -564,8 +564,6 @@
     }
   else if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
     {
-      struct ospf6_inter_router_lsa *router_lsa;
-
       if (IS_OSPF6_DEBUG_EXAMIN (INTER_ROUTER))
         {
           is_debug++;
@@ -604,7 +602,7 @@
     }
 
   /* (1) if cost == LSInfinity or if the LSA is MaxAge */
-  if (cost == LS_INFINITY)
+  if (cost == OSPF_LS_INFINITY)
     {
       if (is_debug)
         zlog_debug ("cost is LS_INFINITY, ignore");
@@ -632,6 +630,7 @@
     }
 
   /* (3) if the prefix is equal to an active configured address range */
+  /*     or if the NU bit is set in the prefix */
   if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_PREFIX))
     {
       range = ospf6_route_lookup (&prefix, oa->range_table);
@@ -643,6 +642,32 @@
             ospf6_route_remove (old, table);
           return;
         }
+
+      if (CHECK_FLAG (prefix_lsa->prefix.prefix_options,
+		      OSPF6_PREFIX_OPTION_NU) ||
+	  CHECK_FLAG (prefix_lsa->prefix.prefix_options,
+		      OSPF6_PREFIX_OPTION_LA))
+	{
+          if (is_debug)
+            zlog_debug ("Prefix has NU/LA bit set, ignore");
+          if (old)
+            ospf6_route_remove (old, table);
+          return;
+	}
+    }
+
+  if (lsa->header->type == htons (OSPF6_LSTYPE_INTER_ROUTER))
+    {
+      /* To pass test suites */
+      if (! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_R) ||
+	  ! OSPF6_OPT_ISSET (router_lsa->options, OSPF6_OPT_V6))
+	{
+          if (is_debug)
+            zlog_debug ("Prefix has NU/LA bit set, ignore");
+          if (old)
+            ospf6_route_remove (old, table);
+          return;
+	}
     }
 
   /* (4) if the routing table entry for the ABR does not exist */
@@ -764,12 +789,34 @@
 
 
 /* Display functions */
+static char *
+ospf6_inter_area_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
+					    int buflen, int pos)
+{
+  struct ospf6_inter_prefix_lsa *prefix_lsa;
+  struct in6_addr in6;
+
+  if (lsa != NULL)
+    {
+      prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+	OSPF6_LSA_HEADER_END (lsa->header);
+
+      ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
+      if (buf)
+	{
+	  inet_ntop (AF_INET6, &in6, buf, buflen);
+	  sprintf (&buf[strlen(buf)], "/%d", prefix_lsa->prefix.prefix_length);
+	}
+    }
+
+  return (buf);
+}
+
 static int
 ospf6_inter_area_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
   struct ospf6_inter_prefix_lsa *prefix_lsa;
-  struct in6_addr in6;
-  char buf[64];
+  char buf[INET6_ADDRSTRLEN];
 
   prefix_lsa = (struct ospf6_inter_prefix_lsa *)
     OSPF6_LSA_HEADER_END (lsa->header);
@@ -781,14 +828,32 @@
                                  buf, sizeof (buf));
   vty_out (vty, "     Prefix Options: %s%s", buf, VNL);
 
-  ospf6_prefix_in6_addr (&in6, &prefix_lsa->prefix);
-  inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-  vty_out (vty, "     Prefix: %s/%d%s", buf,
-           prefix_lsa->prefix.prefix_length, VNL);
+  vty_out (vty, "     Prefix: %s%s",
+	   ospf6_inter_area_prefix_lsa_get_prefix_str (lsa, buf, sizeof(buf),
+						       0), VNL);
 
   return 0;
 }
 
+static char *
+ospf6_inter_area_router_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
+					    int buflen, int pos)
+{
+  struct ospf6_inter_router_lsa *router_lsa;
+
+  if (lsa != NULL)
+    {
+      router_lsa = (struct ospf6_inter_router_lsa *)
+	OSPF6_LSA_HEADER_END (lsa->header);
+
+
+      if (buf)
+	inet_ntop (AF_INET, &router_lsa->router_id, buf, buflen);
+    }
+
+  return (buf);
+}
+
 static int
 ospf6_inter_area_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
@@ -802,6 +867,7 @@
   vty_out (vty, "     Options: %s%s", buf, VNL);
   vty_out (vty, "     Metric: %lu%s",
            (u_long) OSPF6_ABR_SUMMARY_METRIC (router_lsa), VNL);
+
   inet_ntop (AF_INET, &router_lsa->router_id, buf, sizeof (buf));
   vty_out (vty, "     Destination Router ID: %s%s", buf, VNL);
 
@@ -855,14 +921,18 @@
 {
   OSPF6_LSTYPE_INTER_PREFIX,
   "Inter-Prefix",
-  ospf6_inter_area_prefix_lsa_show
+  "IAP",
+  ospf6_inter_area_prefix_lsa_show,
+  ospf6_inter_area_prefix_lsa_get_prefix_str,
 };
 
 struct ospf6_lsa_handler inter_router_handler =
 {
   OSPF6_LSTYPE_INTER_ROUTER,
   "Inter-Router",
-  ospf6_inter_area_router_lsa_show
+  "IAR",
+  ospf6_inter_area_router_lsa_show,
+  ospf6_inter_area_router_lsa_get_prefix_str,
 };
 
 void
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 9934e6b..9a4e30e 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -67,7 +67,8 @@
           zlog_debug ("Schedule SPF Calculation for %s",
 		      OSPF6_AREA (lsa->lsdb->data)->name);
         }
-      ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
+      ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
+			  ospf6_lsadd_to_spf_reason(lsa));
       break;
 
     case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -97,7 +98,8 @@
           zlog_debug ("Schedule SPF Calculation for %s",
                      OSPF6_AREA (lsa->lsdb->data)->name);
         }
-      ospf6_spf_schedule (OSPF6_AREA (lsa->lsdb->data));
+      ospf6_spf_schedule (OSPF6_PROCESS(OSPF6_AREA (lsa->lsdb->data)->ospf6),
+			  ospf6_lsremove_to_spf_reason(lsa));
       break;
 
     case OSPF6_LSTYPE_INTRA_PREFIX:
@@ -164,9 +166,18 @@
   oa->summary_router->scope = oa;
 
   /* set default options */
-  OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+  if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
+    {
+      OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
+      OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
+    }
+  else
+    {
+      OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+      OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
+    }
+
   OSPF6_OPT_SET (oa->options, OSPF6_OPT_E);
-  OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
 
   oa->ospf6 = o;
   listnode_add_sort (o->area_list, oa);
@@ -182,18 +193,21 @@
 void
 ospf6_area_delete (struct ospf6_area *oa)
 {
-  struct listnode *n, *nnode;
+  struct listnode *n;
   struct ospf6_interface *oi;
 
   ospf6_route_table_delete (oa->range_table);
   ospf6_route_table_delete (oa->summary_prefix);
   ospf6_route_table_delete (oa->summary_router);
 
-  /* ospf6 interface list */
-  for (ALL_LIST_ELEMENTS (oa->if_list, n, nnode, oi))
-    {
-      ospf6_interface_delete (oi);
-    }
+  /* The ospf6_interface structs store configuration
+   * information which should not be lost/reset when
+   * deleting an area.
+   * So just detach the interface from the area and
+   * keep it around. */
+  for (ALL_LIST_ELEMENTS_RO (oa->if_list, n, oi))
+    oi->area = NULL;
+
   list_delete (oa->if_list);
 
   ospf6_lsdb_delete (oa->lsdb);
@@ -246,6 +260,7 @@
 
   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
     ospf6_interface_enable (oi);
+  ospf6_abr_enable_area (oa);
 }
 
 void
@@ -258,6 +273,19 @@
 
   for (ALL_LIST_ELEMENTS (oa->if_list, node, nnode, oi))
     ospf6_interface_disable (oi);
+
+  ospf6_abr_disable_area (oa);
+  ospf6_lsdb_remove_all (oa->lsdb);
+  ospf6_lsdb_remove_all (oa->lsdb_self);
+
+  ospf6_spf_table_finish(oa->spf_table);
+  ospf6_route_remove_all(oa->route_table);
+
+  THREAD_OFF (oa->thread_spf_calculation);
+  THREAD_OFF (oa->thread_route_calculation);
+
+  THREAD_OFF (oa->thread_router_lsa);
+  THREAD_OFF (oa->thread_intra_prefix_lsa);
 }
 
 
@@ -401,6 +429,7 @@
     }
 
   ospf6_route_remove (range, oa->range_table);
+
   return CMD_SUCCESS;
 }
 
diff --git a/ospf6d/ospf6_area.h b/ospf6d/ospf6_area.h
index e8a4fbd..655967a 100644
--- a/ospf6d/ospf6_area.h
+++ b/ospf6d/ospf6_area.h
@@ -105,8 +105,6 @@
 #define OSPF6_AREA_TRANSIT    0x04 /* TransitCapability */
 #define OSPF6_AREA_STUB       0x08
 
-#define BACKBONE_AREA_ID (htonl (0))
-#define IS_AREA_BACKBONE(oa) ((oa)->area_id == BACKBONE_AREA_ID)
 #define IS_AREA_ENABLED(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ENABLE))
 #define IS_AREA_ACTIVE(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_ACTIVE))
 #define IS_AREA_TRANSIT(oa) (CHECK_FLAG ((oa)->flag, OSPF6_AREA_TRANSIT))
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index ae0a286..3605e3f 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -174,13 +174,20 @@
       return;
     }
 
-  if (OSPF6_ASBR_METRIC (external) == LS_INFINITY)
+  if (OSPF6_ASBR_METRIC (external) == OSPF_LS_INFINITY)
     {
       if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
         zlog_debug ("Ignore LSA with LSInfinity Metric");
       return;
     }
 
+  if (CHECK_FLAG(external->prefix.prefix_options, OSPF6_PREFIX_OPTION_NU))
+    {
+      if (IS_OSPF6_DEBUG_EXAMIN (AS_EXTERNAL))
+        zlog_debug ("Ignore LSA with NU bit set Metric");
+      return;
+    }
+
   ospf6_linkstate_prefix (lsa->header->adv_router, htonl (0), &asbr_id);
   asbr_entry = ospf6_route_lookup (&asbr_id, ospf6->brouter_table);
   if (asbr_entry == NULL ||
@@ -402,6 +409,8 @@
       ospf6_asbr_redistribute_remove (info->type, route->nexthop[0].ifindex,
                                       &route->prefix);
     }
+
+  ospf6_asbr_routemap_unset (type);
 }
 
 void
@@ -629,7 +638,6 @@
     return CMD_WARNING;
 
   ospf6_asbr_redistribute_unset (type);
-  ospf6_asbr_routemap_unset (type);
   ospf6_asbr_redistribute_set (type);
   return CMD_SUCCESS;
 }
@@ -670,7 +678,6 @@
     return CMD_WARNING;
 
   ospf6_asbr_redistribute_unset (type);
-  ospf6_asbr_routemap_unset (type);
 
   return CMD_SUCCESS;
 }
@@ -890,7 +897,7 @@
   u_int32_t metric;
   char *endp;
   metric = strtoul (arg, &endp, 0);
-  if (metric > LS_INFINITY || *endp != '\0')
+  if (metric > OSPF_LS_INFINITY || *endp != '\0')
     return NULL;
   return XSTRDUP (MTYPE_ROUTE_MAP_COMPILED, arg);
 }
@@ -1161,12 +1168,44 @@
 
 
 /* Display functions */
+static char *
+ospf6_as_external_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
+				      int buflen, int pos)
+{
+  struct ospf6_as_external_lsa *external;
+  struct in6_addr in6;
+  int prefix_length = 0;
+
+  if (lsa)
+    {
+        external = (struct ospf6_as_external_lsa *)
+	  OSPF6_LSA_HEADER_END (lsa->header);
+
+	if (pos == 0)
+	  {
+	    ospf6_prefix_in6_addr (&in6, &external->prefix);
+	    prefix_length = external->prefix.prefix_length;
+	  }
+	else {
+	  in6 = *((struct in6_addr *)
+		  ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
+		   OSPF6_PREFIX_SPACE (external->prefix.prefix_length)));
+	}
+	if (buf)
+	  {
+	    inet_ntop (AF_INET6, &in6, buf, buflen);
+	    if (prefix_length)
+	      sprintf (&buf[strlen(buf)], "/%d", prefix_length);
+	  }
+    }
+  return (buf);
+}
+
 static int
 ospf6_as_external_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
   struct ospf6_as_external_lsa *external;
   char buf[64];
-  struct in6_addr in6, *forwarding;
 
   assert (lsa->header);
   external = (struct ospf6_as_external_lsa *)
@@ -1191,19 +1230,15 @@
            ntohs (external->prefix.prefix_refer_lstype),
            VNL);
 
-  ospf6_prefix_in6_addr (&in6, &external->prefix);
-  inet_ntop (AF_INET6, &in6, buf, sizeof (buf));
-  vty_out (vty, "     Prefix: %s/%d%s", buf,
-           external->prefix.prefix_length, VNL);
+  vty_out (vty, "     Prefix: %s%s",
+	   ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 0), VNL);
 
   /* Forwarding-Address */
   if (CHECK_FLAG (external->bits_metric, OSPF6_ASBR_BIT_F))
     {
-      forwarding = (struct in6_addr *)
-        ((caddr_t) external + sizeof (struct ospf6_as_external_lsa) +
-         OSPF6_PREFIX_SPACE (external->prefix.prefix_length));
-      inet_ntop (AF_INET6, forwarding, buf, sizeof (buf));
-      vty_out (vty, "     Forwarding-Address: %s%s", buf, VNL);
+      vty_out (vty, "     Forwarding-Address: %s%s",
+	       ospf6_as_external_lsa_get_prefix_str (lsa, buf, sizeof(buf), 1),
+	       VNL);
     }
 
   return 0;
@@ -1257,7 +1292,9 @@
 {
   OSPF6_LSTYPE_AS_EXTERNAL,
   "AS-External",
-  ospf6_as_external_lsa_show
+  "ASE",
+  ospf6_as_external_lsa_show,
+  ospf6_as_external_lsa_get_prefix_str
 };
 
 void
@@ -1276,6 +1313,20 @@
 }
 
 void
+ospf6_asbr_redistribute_reset (void)
+{
+  int type;
+
+  for (type = 0; type < ZEBRA_ROUTE_MAX; type++)
+    {
+      if (type == ZEBRA_ROUTE_OSPF6)
+        continue;
+      if (ospf6_zebra_is_redistribute (type))
+        ospf6_asbr_redistribute_unset(type);
+    }
+}
+
+void
 ospf6_asbr_terminate (void)
 {
   route_map_finish ();
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index 72e4914..73770cc 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -89,6 +89,7 @@
 extern int ospf6_redistribute_config_write (struct vty *vty);
 
 extern void ospf6_asbr_init (void);
+extern void ospf6_asbr_redistribute_reset (void);
 extern void ospf6_asbr_terminate (void);
 
 extern int config_write_ospf6_debug_asbr (struct vty *vty);
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index b815972..49ed6e2 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -113,7 +113,7 @@
   ospf6_lsdb_add (ospf6_lsa_copy (lsa), lsdb_self);
 
   lsa->refresh = thread_add_timer (master, ospf6_lsa_refresh, lsa,
-                                   LS_REFRESH_TIME);
+                                   OSPF_LS_REFRESH_TIME);
 
   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
       IS_OSPF6_DEBUG_ORIGINATE_TYPE (lsa->header->type))
@@ -122,10 +122,8 @@
       ospf6_lsa_header_print (lsa);
     }
 
-  if (old)
-    ospf6_flood_clear (old);
-  ospf6_flood (NULL, lsa);
   ospf6_install_lsa (lsa);
+  ospf6_flood (NULL, lsa);
 }
 
 void
@@ -208,8 +206,8 @@
 void
 ospf6_install_lsa (struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsa *old;
   struct timeval now;
+  struct ospf6_lsa *old;
 
   if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type) ||
       IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
@@ -222,16 +220,36 @@
   if (old)
     {
       THREAD_OFF (old->expire);
+      THREAD_OFF (old->refresh);
       ospf6_flood_clear (old);
     }
 
   quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
   if (! OSPF6_LSA_IS_MAXAGE (lsa))
     lsa->expire = thread_add_timer (master, ospf6_lsa_expire, lsa,
-                                    MAXAGE + lsa->birth.tv_sec - now.tv_sec);
+                                    OSPF_LSA_MAXAGE + lsa->birth.tv_sec - now.tv_sec);
   else
     lsa->expire = NULL;
 
+  if (OSPF6_LSA_IS_SEQWRAP(lsa) &&
+      ! (CHECK_FLAG(lsa->flag,OSPF6_LSA_SEQWRAPPED) &&
+         lsa->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER)))
+   {
+     if (IS_OSPF6_DEBUG_EXAMIN_TYPE (lsa->header->type))
+       zlog_debug("lsa install wrapping: sequence 0x%x",
+                  ntohl(lsa->header->seqnum));
+     SET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
+     /* in lieu of premature_aging, since we do not want to recreate this lsa
+      * and/or mess with timers etc, we just want to wrap the sequence number
+      * and reflood the lsa before continuing.
+      * NOTE: Flood needs to be called right after this function call, by the
+      * caller
+      */
+     lsa->header->seqnum = htonl (OSPF_MAX_SEQUENCE_NUMBER);
+     lsa->header->age = htons (OSPF_LSA_MAXAGE);
+     ospf6_lsa_checksum (lsa->header);
+   }
+
   /* actually install */
   lsa->installed = now;
   ospf6_lsdb_add (lsa, lsa->lsdb);
@@ -292,7 +310,7 @@
               if (ospf6_lsa_compare (lsa, req) > 0)
                 {
                   if (is_debug)
-                    zlog_debug ("Requesting is newer, next neighbor");
+                    zlog_debug ("Requesting is older, next neighbor");
                   continue;
                 }
 
@@ -300,18 +318,30 @@
                  examin next neighbor */
               if (ospf6_lsa_compare (lsa, req) == 0)
                 {
-                  if (is_debug)
-                    zlog_debug ("Requesting the same, remove it, next neighbor");
+		  if (is_debug)
+		    zlog_debug ("Requesting the same, remove it, next neighbor");
+		  if (req == on->last_ls_req)
+		    {
+		      ospf6_lsa_unlock (req);
+		      on->last_ls_req = NULL;
+		    }
                   ospf6_lsdb_remove (req, on->request_list);
+		  ospf6_check_nbr_loading (on);
                   continue;
                 }
 
               /* If the new LSA is more recent, delete from request-list */
               if (ospf6_lsa_compare (lsa, req) < 0)
                 {
-                  if (is_debug)
-                    zlog_debug ("Received is newer, remove requesting");
+		  if (is_debug)
+		    zlog_debug ("Received is newer, remove requesting");
+		  if (req == on->last_ls_req)
+		    {
+		      ospf6_lsa_unlock (req);
+		      on->last_ls_req = NULL;
+		    }
                   ospf6_lsdb_remove (req, on->request_list);
+		  ospf6_check_nbr_loading (on);
                   /* fall through */
                 }
             }
@@ -358,17 +388,22 @@
 
   /* (4) If the new LSA was received on this interface,
      and the interface state is BDR, examin next interface */
-  if (from && from->ospf6_if == oi && oi->state == OSPF6_INTERFACE_BDR)
+  if (from && from->ospf6_if == oi)
     {
-      if (is_debug)
-        zlog_debug ("Received is from the I/F, itself BDR, next interface");
-      return;
+      if (oi->state == OSPF6_INTERFACE_BDR)
+	{
+	  if (is_debug)
+	    zlog_debug ("Received is from the I/F, itself BDR, next interface");
+	  return;
+	}
+      SET_FLAG(lsa->flag, OSPF6_LSA_FLOODBACK);
     }
 
   /* (5) flood the LSA out the interface. */
   if (is_debug)
     zlog_debug ("Schedule flooding for the interface");
-  if (if_is_broadcast (oi->interface))
+  if ((oi->type == OSPF_IFTYPE_BROADCAST) ||
+      (oi->type == OSPF_IFTYPE_POINTOPOINT))
     {
       ospf6_lsdb_add (ospf6_lsa_copy (lsa), oi->lsupdate_list);
       if (oi->thread_send_lsupdate == NULL)
@@ -530,15 +565,6 @@
   assert (from && from->ospf6_if);
   oi = from->ospf6_if;
 
-  /* LSA has been flood back out receiving interface.
-     No acknowledgement sent. */
-  if (CHECK_FLAG (lsa->flag, OSPF6_LSA_FLOODBACK))
-    {
-      if (is_debug)
-        zlog_debug ("No acknowledgement (BDR & FloodBack)");
-      return;
-    }
-
   /* LSA is more recent than database copy, but was not flooded
      back out receiving interface. Delayed acknowledgement sent
      if advertisement received from Designated Router,
@@ -797,7 +823,7 @@
     {
       /* log */
       if (is_debug)
-        zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
+	zlog_debug ("Drop MaxAge LSA with direct acknowledgement.");
 
       /* a) Acknowledge back to neighbor (Direct acknowledgement, 13.5) */
       ospf6_lsdb_add (ospf6_lsa_copy (new), from->lsack_list);
@@ -837,7 +863,7 @@
           struct timeval now, res;
           quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
           timersub (&now, &old->installed, &res);
-          if (res.tv_sec < MIN_LS_ARRIVAL)
+          if (res.tv_sec < OSPF_MIN_LS_ARRIVAL)
             {
               if (is_debug)
                 zlog_debug ("LSA can't be updated within MinLSArrival, discard");
@@ -849,7 +875,11 @@
       quagga_gettime (QUAGGA_CLK_MONOTONIC, &new->received);
 
       if (is_debug)
-        zlog_debug ("Flood, Install, Possibly acknowledge the received LSA");
+        zlog_debug ("Install, Flood, Possibly acknowledge the received LSA");
+
+      /* Remove older copies of this LSA from retx lists */
+      if (old)
+	ospf6_flood_clear (old);
 
       /* (b) immediately flood and (c) remove from all retrans-list */
       /* Prevent self-originated LSA to be flooded. this is to make
@@ -858,10 +888,6 @@
       if (new->header->adv_router != from->ospf6_if->area->ospf6->router_id)
         ospf6_flood (from, new);
 
-      /* (c) Remove the current database copy from all neighbors' Link
-             state retransmission lists. */
-      /* XXX, flood_clear ? */
-
       /* (d), installing lsdb, which may cause routing
               table calculation (replacing database copy) */
       ospf6_install_lsa (new);
@@ -944,15 +970,15 @@
       /* If database copy is in 'Seqnumber Wrapping',
          simply discard the received LSA */
       if (OSPF6_LSA_IS_MAXAGE (old) &&
-          old->header->seqnum == htonl (MAX_SEQUENCE_NUMBER))
+          old->header->seqnum == htonl (OSPF_MAX_SEQUENCE_NUMBER))
         {
           if (is_debug)
             {
               zlog_debug ("The LSA is in Seqnumber Wrapping");
               zlog_debug ("MaxAge & MaxSeqNum, discard");
             }
-          ospf6_lsa_delete (new);
-          return;
+	  ospf6_lsa_delete (new);
+	  return;
         }
 
       /* Otherwise, Send database copy of this LSA to this neighbor */
@@ -969,8 +995,8 @@
           if (from->thread_send_lsupdate == NULL)
             from->thread_send_lsupdate =
               thread_add_event (master, ospf6_lsupdate_send_neighbor, from, 0);
-          ospf6_lsa_delete (new);
-          return;
+	  ospf6_lsa_delete (new);
+	  return;
         }
       return;
     }
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 40cda24..b0f1119 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -73,14 +73,20 @@
 
 /* schedule routing table recalculation */
 static void
-ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa)
+ospf6_interface_lsdb_hook (struct ospf6_lsa *lsa, unsigned int reason)
 {
+  struct ospf6_interface *oi;
+
+  if (lsa == NULL)
+    return;
+
+  oi = lsa->lsdb->data;
   switch (ntohs (lsa->header->type))
     {
       case OSPF6_LSTYPE_LINK:
-        if (OSPF6_INTERFACE (lsa->lsdb->data)->state == OSPF6_INTERFACE_DR)
-          OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (OSPF6_INTERFACE (lsa->lsdb->data));
-        ospf6_spf_schedule (OSPF6_INTERFACE (lsa->lsdb->data)->area);
+        if (oi->state == OSPF6_INTERFACE_DR)
+          OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT (oi);
+        ospf6_spf_schedule (oi->area->ospf6, reason);
         break;
 
       default:
@@ -88,6 +94,29 @@
     }
 }
 
+static void
+ospf6_interface_lsdb_hook_add (struct ospf6_lsa *lsa)
+{
+  ospf6_interface_lsdb_hook(lsa, ospf6_lsadd_to_spf_reason(lsa));
+}
+
+static void
+ospf6_interface_lsdb_hook_remove (struct ospf6_lsa *lsa)
+{
+  ospf6_interface_lsdb_hook(lsa, ospf6_lsremove_to_spf_reason(lsa));
+}
+
+static u_char
+ospf6_default_iftype(struct interface *ifp)
+{
+  if (if_is_pointopoint (ifp))
+    return OSPF_IFTYPE_POINTOPOINT;
+  else if (if_is_loopback (ifp))
+    return OSPF_IFTYPE_LOOPBACK;
+  else
+    return OSPF_IFTYPE_BROADCAST;
+}
+
 /* Create new ospf6 interface structure */
 struct ospf6_interface *
 ospf6_interface_create (struct interface *ifp)
@@ -112,10 +141,11 @@
   oi->transdelay = OSPF6_INTERFACE_TRANSDELAY;
   oi->priority = OSPF6_INTERFACE_PRIORITY;
 
-  oi->hello_interval = OSPF6_INTERFACE_HELLO_INTERVAL;
-  oi->dead_interval = OSPF6_INTERFACE_DEAD_INTERVAL;
-  oi->rxmt_interval = OSPF6_INTERFACE_RXMT_INTERVAL;
+  oi->hello_interval = OSPF_HELLO_INTERVAL_DEFAULT;
+  oi->dead_interval = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
+  oi->rxmt_interval = OSPF_RETRANSMIT_INTERVAL_DEFAULT;
   oi->cost = OSPF6_INTERFACE_COST;
+  oi->type = ospf6_default_iftype (ifp);
   oi->state = OSPF6_INTERFACE_DOWN;
   oi->flag = 0;
   oi->mtu_ignore = 0;
@@ -134,8 +164,8 @@
   oi->lsupdate_list = ospf6_lsdb_create (oi);
   oi->lsack_list = ospf6_lsdb_create (oi);
   oi->lsdb = ospf6_lsdb_create (oi);
-  oi->lsdb->hook_add = ospf6_interface_lsdb_hook;
-  oi->lsdb->hook_remove = ospf6_interface_lsdb_hook;
+  oi->lsdb->hook_add = ospf6_interface_lsdb_hook_add;
+  oi->lsdb->hook_remove = ospf6_interface_lsdb_hook_remove;
   oi->lsdb_self = ospf6_lsdb_create (oi);
 
   oi->route_connected = OSPF6_ROUTE_TABLE_CREATE (INTERFACE, CONNECTED_ROUTES);
@@ -189,31 +219,28 @@
 ospf6_interface_enable (struct ospf6_interface *oi)
 {
   UNSET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
-
-  oi->thread_send_hello =
-    thread_add_event (master, ospf6_hello_send, oi, 0);
+  ospf6_interface_state_update (oi->interface);
 }
 
 void
 ospf6_interface_disable (struct ospf6_interface *oi)
 {
-  struct listnode *node, *nnode;
-  struct ospf6_neighbor *on;
-
   SET_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE);
 
-  for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on))
-      ospf6_neighbor_delete (on);
-
-  list_delete_all_node (oi->neighbor_list);
+  thread_execute (master, interface_down, oi, 0);
 
   ospf6_lsdb_remove_all (oi->lsdb);
+  ospf6_lsdb_remove_all (oi->lsdb_self);
   ospf6_lsdb_remove_all (oi->lsupdate_list);
   ospf6_lsdb_remove_all (oi->lsack_list);
 
   THREAD_OFF (oi->thread_send_hello);
   THREAD_OFF (oi->thread_send_lsupdate);
   THREAD_OFF (oi->thread_send_lsack);
+
+  THREAD_OFF (oi->thread_network_lsa);
+  THREAD_OFF (oi->thread_link_lsa);
+  THREAD_OFF (oi->thread_intra_prefix_lsa);
 }
 
 static struct in6_addr *
@@ -260,8 +287,7 @@
     }
 
   /* interface start */
-  if (oi->area)
-    thread_add_event (master, interface_up, oi, 0);
+  ospf6_interface_state_update(oi->interface);
 }
 
 void
@@ -297,8 +323,12 @@
     return;
   if (oi->area == NULL)
     return;
+  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
+    return;
 
-  if (if_is_up (ifp))
+  if (if_is_operative (ifp)
+      && (ospf6_interface_get_linklocal_address(oi->interface)
+          || if_is_loopback(oi->interface)))
     thread_add_event (master, interface_up, oi, 0);
   else
     thread_add_event (master, interface_down, oi, 0);
@@ -325,6 +355,9 @@
   if (oi->area == NULL)
     return;
 
+  if (CHECK_FLAG (oi->flag, OSPF6_INTERFACE_DISABLE))
+    return;
+
   /* update "route to advertise" interface route table */
   ospf6_route_remove_all (oi->route_connected);
 
@@ -401,6 +434,7 @@
       (next_state != OSPF6_INTERFACE_DR &&
        next_state != OSPF6_INTERFACE_BDR))
     ospf6_sso (oi->interface->ifindex, &alldrouters6, IPV6_LEAVE_GROUP);
+
   if ((prev_state != OSPF6_INTERFACE_DR &&
        prev_state != OSPF6_INTERFACE_BDR) &&
       (next_state == OSPF6_INTERFACE_DR ||
@@ -606,7 +640,7 @@
 		oi->interface->name);
 
   /* check physical interface is up */
-  if (! if_is_up (oi->interface))
+  if (! if_is_operative (oi->interface))
     {
       if (IS_OSPF6_DEBUG_INTERFACE)
         zlog_debug ("Interface %s is down, can't execute [InterfaceUp]",
@@ -614,6 +648,16 @@
       return 0;
     }
 
+  /* check interface has a link-local address */
+  if (! (ospf6_interface_get_linklocal_address(oi->interface)
+         || if_is_loopback(oi->interface)))
+    {
+      if (IS_OSPF6_DEBUG_INTERFACE)
+	zlog_debug ("Interface %s has no link local address, can't execute [InterfaceUp]",
+		    oi->interface->name);
+	return 0;
+    }
+
   /* if already enabled, do nothing */
   if (oi->state > OSPF6_INTERFACE_DOWN)
     {
@@ -623,6 +667,14 @@
       return 0;
     }
 
+  /* If no area assigned, return */
+  if (oi->area == NULL)
+    {
+      zlog_debug ("%s: Not scheduleing Hello for %s as there is no area assigned yet", __func__,
+		  oi->interface->name);
+      return 0;
+    }
+
   /* Join AllSPFRouters */
   ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP);
 
@@ -631,11 +683,13 @@
 
   /* Schedule Hello */
   if (! CHECK_FLAG (oi->flag, OSPF6_INTERFACE_PASSIVE))
-    thread_add_event (master, ospf6_hello_send, oi, 0);
+    oi->thread_send_hello = thread_add_event (master, ospf6_hello_send, oi, 0);
 
   /* decide next interface state */
-  if (if_is_pointopoint (oi->interface))
+  if ((if_is_pointopoint (oi->interface)) ||
+      (oi->type == OSPF_IFTYPE_POINTOPOINT)) {
     ospf6_interface_state_change (OSPF6_INTERFACE_POINTTOPOINT, oi);
+  }
   else if (oi->priority == 0)
     ospf6_interface_state_change (OSPF6_INTERFACE_DROTHER, oi);
   else
@@ -717,6 +771,9 @@
     zlog_debug ("Interface Event %s: [InterfaceDown]",
 		oi->interface->name);
 
+  /* Stop Hellos */
+  THREAD_OFF (oi->thread_send_hello);
+
   /* Leave AllSPFRouters */
   if (oi->state > OSPF6_INTERFACE_DOWN)
     ospf6_sso (oi->interface->ifindex, &allspfrouters6, IPV6_LEAVE_GROUP);
@@ -728,6 +785,10 @@
   
   list_delete_all_node (oi->neighbor_list);
 
+  /* When interface state is reset, also reset information about
+   * DR election, as it is no longer valid. */
+  oi->drouter = oi->prev_drouter = htonl(0);
+  oi->bdrouter = oi->prev_bdrouter = htonl(0);
   return 0;
 }
 
@@ -758,7 +819,7 @@
     type = "UNKNOWN";
 
   vty_out (vty, "%s is %s, type %s%s",
-           ifp->name, updown[if_is_up (ifp)], type,
+           ifp->name, updown[if_is_operative (ifp)], type,
 	   VNL);
   vty_out (vty, "  Interface ID: %d%s", ifp->ifindex, VNL);
 
@@ -1292,7 +1353,10 @@
 
   oi->priority = strtol (argv[0], NULL, 10);
 
-  if (oi->area)
+  if (oi->area &&
+      (oi->state == OSPF6_INTERFACE_DROTHER ||
+       oi->state == OSPF6_INTERFACE_BDR ||
+       oi->state == OSPF6_INTERFACE_DR))
     ospf6_interface_state_change (dr_election (oi), oi);
 
   return CMD_SUCCESS;
@@ -1516,6 +1580,86 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (ipv6_ospf6_network,
+       ipv6_ospf6_network_cmd,
+       "ipv6 ospf6 network (broadcast|point-to-point)",
+       IP6_STR
+       OSPF6_STR
+       "Network Type\n"
+       "Specify OSPFv6 broadcast network\n"
+       "Specify OSPF6 point-to-point network\n"
+       )
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL) {
+    oi = ospf6_interface_create (ifp);
+  }
+  assert (oi);
+
+  if (strncmp (argv[0], "b", 1) == 0)
+    {
+      if (oi->type == OSPF_IFTYPE_BROADCAST)
+	return CMD_SUCCESS;
+
+      oi->type = OSPF_IFTYPE_BROADCAST;
+    }
+    else if (strncmp (argv[0], "point-to-p", 10) == 0)
+      {
+	if (oi->type == OSPF_IFTYPE_POINTOPOINT) {
+	  return CMD_SUCCESS;
+	}
+	oi->type = OSPF_IFTYPE_POINTOPOINT;
+      }
+
+  /* Reset the interface */
+  thread_add_event (master, interface_down, oi, 0);
+  thread_add_event (master, interface_up, oi, 0);
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ipv6_ospf6_network,
+       no_ipv6_ospf6_network_cmd,
+       "no ipv6 ospf6 network",
+       NO_STR
+       IP6_STR
+       OSPF6_STR
+       "Network Type\n"
+       "Default to whatever interface type system specifies"
+       )
+{
+  struct ospf6_interface *oi;
+  struct interface *ifp;
+  int type;
+
+  ifp = (struct interface *) vty->index;
+  assert (ifp);
+
+  oi = (struct ospf6_interface *) ifp->info;
+  if (oi == NULL) {
+    return CMD_SUCCESS;
+  }
+
+  type = ospf6_default_iftype (ifp);
+  if (oi->type == type)
+    {
+      return CMD_SUCCESS;
+    }
+  oi->type = type;
+
+  /* Reset the interface */
+  thread_add_event (master, interface_down, oi, 0);
+  thread_add_event (master, interface_up, oi, 0);
+
+  return CMD_SUCCESS;
+}
+
 static int
 config_write_ospf6_interface (struct vty *vty)
 {
@@ -1575,6 +1719,11 @@
       if (oi->mtu_ignore)
         vty_out (vty, " ipv6 ospf6 mtu-ignore%s", VNL);
 
+      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+        vty_out (vty, " ipv6 ospf6 network point-to-point%s", VNL);
+      else if (oi->type == OSPF_IFTYPE_BROADCAST)
+	vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL);
+
       vty_out (vty, "!%s", VNL);
     }
   return 0;
@@ -1632,6 +1781,9 @@
 
   install_element (INTERFACE_NODE, &ipv6_ospf6_advertise_prefix_list_cmd);
   install_element (INTERFACE_NODE, &no_ipv6_ospf6_advertise_prefix_list_cmd);
+
+  install_element (INTERFACE_NODE, &ipv6_ospf6_network_cmd);
+  install_element (INTERFACE_NODE, &no_ipv6_ospf6_network_cmd);
 }
 
 DEFUN (debug_ospf6_interface,
diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h
index d80b073..808f096 100644
--- a/ospf6d/ospf6_interface.h
+++ b/ospf6d/ospf6_interface.h
@@ -56,6 +56,9 @@
   /* I/F transmission delay */
   u_int32_t transdelay;
 
+  /* Network Type */
+  u_char type;
+
   /* Router Priority */
   u_char priority;
 
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 9bc603b..4ad7521 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -46,7 +46,7 @@
 #include "ospf6_abr.h"
 #include "ospf6_flood.h"
 #include "ospf6d.h"
-
+#include "ospf6_spf.h"
 
 unsigned char conf_debug_ospf6_brouter = 0;
 u_int32_t conf_debug_ospf6_brouter_specific_router_id;
@@ -56,6 +56,42 @@
 /* RFC2740 3.4.3.1 Router-LSA */
 /******************************/
 
+static char *
+ospf6_router_lsa_get_nbr_id (struct ospf6_lsa *lsa, char *buf, int buflen,
+			     int pos)
+{
+  struct ospf6_router_lsa *router_lsa;
+  struct ospf6_router_lsdesc *lsdesc;
+  char *start, *end;
+  char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
+
+  if (lsa)
+    {
+      router_lsa = (struct ospf6_router_lsa *)
+	((char *) lsa->header + sizeof (struct ospf6_lsa_header));
+      start = (char *) router_lsa + sizeof (struct ospf6_router_lsa);
+      end = (char *) lsa->header + ntohs (lsa->header->length);
+
+      lsdesc = (struct ospf6_router_lsdesc *)
+	(start + pos*(sizeof (struct ospf6_router_lsdesc)));
+      if ((char *)lsdesc < end)
+	{
+	  if (buf && (buflen > INET_ADDRSTRLEN*2))
+	    {
+	      inet_ntop (AF_INET, &lsdesc->neighbor_interface_id,
+			 buf1, sizeof(buf1));
+	      inet_ntop (AF_INET, &lsdesc->neighbor_router_id,
+			 buf2, sizeof(buf2));
+	      sprintf (buf, "%s/%s", buf2, buf1);
+	    }
+	}
+      else
+	return NULL;
+    }
+
+  return buf;
+}
+
 static int
 ospf6_router_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
@@ -105,6 +141,29 @@
 }
 
 int
+ospf6_router_is_stub_router (struct ospf6_lsa *lsa)
+{
+  struct ospf6_router_lsa *rtr_lsa;
+
+  if (lsa != NULL && OSPF6_LSA_IS_TYPE (ROUTER, lsa))
+    {
+      rtr_lsa = (struct ospf6_router_lsa *)
+	((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+      if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_R))
+	{
+	  return (OSPF6_IS_STUB_ROUTER);
+	}
+      else if (!OSPF6_OPT_ISSET (rtr_lsa->options, OSPF6_OPT_V6))
+	{
+	  return (OSPF6_IS_STUB_ROUTER_V6);
+	}
+    }
+
+  return (OSPF6_NOT_STUB_ROUTER);
+}
+
+int
 ospf6_router_lsa_originate (struct thread *thread)
 {
   struct ospf6_area *oa;
@@ -215,7 +274,7 @@
         }
 
       /* Point-to-Point interfaces */
-      if (if_is_pointopoint (oi->interface))
+      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
         {
           for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, j, on))
             {
@@ -233,7 +292,7 @@
         }
 
       /* Broadcast and NBMA interfaces */
-      if (if_is_broadcast (oi->interface))
+      else if (oi->type == OSPF_IFTYPE_BROADCAST)
         {
           /* If this router is not DR,
              and If this router not fully adjacent with DR,
@@ -261,6 +320,10 @@
 
           lsdesc++;
         }
+      else
+	{
+	  assert (0);		/* Unknown interface type */
+	}
 
       /* Virtual links */
         /* xxx */
@@ -268,35 +331,26 @@
         /* xxx */
     }
 
-  if ((caddr_t) lsdesc != (caddr_t) router_lsa +
-                          sizeof (struct ospf6_router_lsa))
-    {
-      /* Fill LSA Header */
-      lsa_header->age = 0;
-      lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
-      lsa_header->id = htonl (link_state_id);
-      lsa_header->adv_router = oa->ospf6->router_id;
-      lsa_header->seqnum =
-        ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
-                             lsa_header->adv_router, oa->lsdb);
-      lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
+  /* Fill LSA Header */
+  lsa_header->age = 0;
+  lsa_header->type = htons (OSPF6_LSTYPE_ROUTER);
+  lsa_header->id = htonl (link_state_id);
+  lsa_header->adv_router = oa->ospf6->router_id;
+  lsa_header->seqnum =
+    ospf6_new_ls_seqnum (lsa_header->type, lsa_header->id,
+                         lsa_header->adv_router, oa->lsdb);
+  lsa_header->length = htons ((caddr_t) lsdesc - (caddr_t) buffer);
 
-      /* LSA checksum */
-      ospf6_lsa_checksum (lsa_header);
+  /* LSA checksum */
+  ospf6_lsa_checksum (lsa_header);
 
-      /* create LSA */
-      lsa = ospf6_lsa_create (lsa_header);
+  /* create LSA */
+  lsa = ospf6_lsa_create (lsa_header);
 
-      /* Originate */
-      ospf6_lsa_originate_area (lsa, oa);
+  /* Originate */
+  ospf6_lsa_originate_area (lsa, oa);
 
-      link_state_id ++;
-    }
-  else
-    {
-      if (IS_OSPF6_DEBUG_ORIGINATE (ROUTER))
-        zlog_debug ("Nothing to describe in Router-LSA, suppress");
-    }
+  link_state_id ++;
 
   /* Do premature-aging of rest, undesired Router-LSAs */
   type = ntohs (OSPF6_LSTYPE_ROUTER);
@@ -316,6 +370,36 @@
 /* RFC2740 3.4.3.2 Network-LSA */
 /*******************************/
 
+static char *
+ospf6_network_lsa_get_ar_id (struct ospf6_lsa *lsa, char *buf, int buflen,
+			     int pos)
+{
+  char *start, *end, *current;
+  struct ospf6_network_lsa *network_lsa;
+  struct ospf6_network_lsdesc *lsdesc;
+
+  if (lsa)
+    {
+      network_lsa = (struct ospf6_network_lsa *)
+	((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+      start = (char *) network_lsa + sizeof (struct ospf6_network_lsa);
+      end = (char *) lsa->header + ntohs (lsa->header->length);
+      current = start + pos*(sizeof (struct ospf6_network_lsdesc));
+
+      if ((current + sizeof(struct ospf6_network_lsdesc)) <= end)
+	{
+	  lsdesc = (struct ospf6_network_lsdesc *)current;
+	  if (buf)
+	    inet_ntop (AF_INET, &lsdesc->router_id, buf, buflen);
+	}
+      else
+	return NULL;
+    }
+
+  return (buf);
+}
+
 static int
 ospf6_network_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
@@ -462,6 +546,61 @@
 /* RFC2740 3.4.3.6 Link-LSA */
 /****************************/
 
+static char *
+ospf6_link_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf, int buflen,
+			       int pos)
+{
+  char *start, *end, *current;
+  struct ospf6_link_lsa *link_lsa;
+  struct in6_addr in6;
+  struct ospf6_prefix *prefix;
+  int cnt = 0, prefixnum;
+
+  if (lsa)
+    {
+      link_lsa = (struct ospf6_link_lsa *)
+	((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+      if (pos == 0) {
+	inet_ntop (AF_INET6, &link_lsa->linklocal_addr, buf, buflen);
+	return (buf);
+      }
+
+      prefixnum = ntohl (link_lsa->prefix_num);
+      if (pos > prefixnum)
+	return (NULL);
+
+      start = (char *) link_lsa + sizeof (struct ospf6_link_lsa);
+      end = (char *) lsa->header + ntohs (lsa->header->length);
+      current = start;
+
+      do
+	{
+	  prefix = (struct ospf6_prefix *) current;
+	  if (prefix->prefix_length == 0 ||
+	      current + OSPF6_PREFIX_SIZE (prefix) > end)
+	    {
+	      return (NULL);
+	    }
+
+	  if (cnt < pos)
+	    {
+	      current = start + pos*OSPF6_PREFIX_SIZE(prefix);
+	      cnt++;
+	    }
+	  else
+	    {
+	      memset (&in6, 0, sizeof (in6));
+	      memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
+		      OSPF6_PREFIX_SPACE (prefix->prefix_length));
+	      inet_ntop (AF_INET6, &in6, buf, buflen);
+	      return (buf);
+	    }
+	} while (current <= end);
+    }
+  return (NULL);
+}
+
 static int
 ospf6_link_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
 {
@@ -614,6 +753,56 @@
 /*****************************************/
 /* RFC2740 3.4.3.7 Intra-Area-Prefix-LSA */
 /*****************************************/
+static char *
+ospf6_intra_prefix_lsa_get_prefix_str (struct ospf6_lsa *lsa, char *buf,
+				       int buflen, int pos)
+{
+  char *start, *end, *current;
+  struct ospf6_intra_prefix_lsa *intra_prefix_lsa;
+  struct in6_addr in6;
+  int prefixnum, cnt = 0;
+  struct ospf6_prefix *prefix;
+
+  if (lsa)
+    {
+      intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+	((caddr_t) lsa->header + sizeof (struct ospf6_lsa_header));
+
+      prefixnum = ntohs (intra_prefix_lsa->prefix_num);
+      if (pos > prefixnum)
+	return (NULL);
+
+      start = (char *) intra_prefix_lsa + sizeof (struct ospf6_intra_prefix_lsa);
+      end = (char *) lsa->header + ntohs (lsa->header->length);
+      current = start;
+
+      do
+	{
+	  prefix = (struct ospf6_prefix *) current;
+	  if (prefix->prefix_length == 0 ||
+	      current + OSPF6_PREFIX_SIZE (prefix) > end)
+	    {
+	      return NULL;
+	    }
+
+	  if (cnt < pos)
+	    {
+	      current = start + pos*OSPF6_PREFIX_SIZE(prefix);
+	      cnt++;
+	    }
+	  else
+	    {
+	      memset (&in6, 0, sizeof (in6));
+	      memcpy (&in6, OSPF6_PREFIX_BODY (prefix),
+		      OSPF6_PREFIX_SPACE (prefix->prefix_length));
+	      inet_ntop (AF_INET6, &in6, buf, buflen);
+	      sprintf(&buf[strlen(buf)], "/%d", prefix->prefix_length);
+	      return (buf);
+	    }
+	} while (current <= end);
+    }
+  return (buf);
+}
 
 static int
 ospf6_intra_prefix_lsa_show (struct vty *vty, struct ospf6_lsa *lsa)
@@ -1029,6 +1218,8 @@
   struct ospf6_prefix *op;
   char *start, *current, *end;
   char buf[64];
+  struct interface *ifp;
+  int direct_connect = 0;
 
   if (OSPF6_LSA_IS_MAXAGE (lsa))
     return;
@@ -1065,6 +1256,12 @@
       return;
     }
 
+  if (intra_prefix_lsa->ref_adv_router == oa->ospf6->router_id)
+    {
+      /* the intra-prefix are directly connected */
+      direct_connect = 1;
+    }
+
   prefix_num = ntohs (intra_prefix_lsa->prefix_num);
   start = (caddr_t) intra_prefix_lsa +
           sizeof (struct ospf6_intra_prefix_lsa);
@@ -1077,6 +1274,20 @@
       if (end < current + OSPF6_PREFIX_SIZE (op))
         break;
 
+      /* Appendix A.4.1.1 */
+      if (CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_NU) ||
+	  CHECK_FLAG(op->prefix_options, OSPF6_PREFIX_OPTION_LA))
+	{
+	  if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
+	    {
+	      ospf6_linkstate_prefix2str ((struct prefix *)OSPF6_PREFIX_BODY(op),
+					  buf, sizeof (buf));
+	      zlog_debug ("%s: Skipping Prefix %s has NU/LA option set",
+			  __func__, buf);
+	    }
+	  continue;
+	}
+
       route = ospf6_route_create ();
 
       memset (&route->prefix, 0, sizeof (struct prefix));
@@ -1095,9 +1306,18 @@
       route->path.cost = ls_entry->path.cost +
                          ntohs (op->prefix_metric);
 
-      for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
-           i < OSPF6_MULTI_PATH_LIMIT; i++)
-        ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
+      if (direct_connect)
+        {
+          ifp = if_lookup_prefix(&route->prefix);
+          if (ifp)
+            route->nexthop[0].ifindex = ifp->ifindex;
+        }
+      else
+        {
+          for (i = 0; ospf6_nexthop_is_set (&ls_entry->nexthop[i]) &&
+               i < OSPF6_MULTI_PATH_LIMIT; i++)
+            ospf6_nexthop_copy (&route->nexthop[i], &ls_entry->nexthop[i]);
+        }
 
       if (IS_OSPF6_DEBUG_EXAMIN (INTRA_PREFIX))
         {
@@ -1342,6 +1562,10 @@
           ! CHECK_FLAG (brouter->path.router_bits, OSPF6_ROUTER_BIT_B))
         continue;
 
+      if (! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_V6) ||
+	  ! OSPF6_OPT_ISSET (brouter->path.options, OSPF6_OPT_R))
+	continue;
+
       copy = ospf6_route_copy (brouter);
       copy->type = OSPF6_DEST_TYPE_ROUTER;
       copy->path.area_id = oa->area_id;
@@ -1419,28 +1643,36 @@
 {
   OSPF6_LSTYPE_ROUTER,
   "Router",
-  ospf6_router_lsa_show
+  "Rtr",
+  ospf6_router_lsa_show,
+  ospf6_router_lsa_get_nbr_id
 };
 
 struct ospf6_lsa_handler network_handler =
 {
   OSPF6_LSTYPE_NETWORK,
   "Network",
-  ospf6_network_lsa_show
+  "Net",
+  ospf6_network_lsa_show,
+  ospf6_network_lsa_get_ar_id
 };
 
 struct ospf6_lsa_handler link_handler =
 {
   OSPF6_LSTYPE_LINK,
   "Link",
-  ospf6_link_lsa_show
+  "Lnk",
+  ospf6_link_lsa_show,
+  ospf6_link_lsa_get_prefix_str
 };
 
 struct ospf6_lsa_handler intra_prefix_handler =
 {
   OSPF6_LSTYPE_INTRA_PREFIX,
   "Intra-Prefix",
-  ospf6_intra_prefix_lsa_show
+  "INP",
+  ospf6_intra_prefix_lsa_show,
+  ospf6_intra_prefix_lsa_get_prefix_str
 };
 
 void
diff --git a/ospf6d/ospf6_intra.h b/ospf6d/ospf6_intra.h
index 3810174..e909da2 100644
--- a/ospf6d/ospf6_intra.h
+++ b/ospf6d/ospf6_intra.h
@@ -94,6 +94,13 @@
 #define OSPF6_ROUTER_LSDESC_STUB_NETWORK       3
 #define OSPF6_ROUTER_LSDESC_VIRTUAL_LINK       4
 
+enum stub_router_mode
+  {
+    OSPF6_NOT_STUB_ROUTER,
+    OSPF6_IS_STUB_ROUTER,
+    OSPF6_IS_STUB_ROUTER_V6,
+  };
+
 #define ROUTER_LSDESC_IS_TYPE(t,x)                         \
   ((((struct ospf6_router_lsdesc *)(x))->type ==           \
    OSPF6_ROUTER_LSDESC_ ## t) ? 1 : 0)
@@ -149,32 +156,37 @@
 
 #define OSPF6_ROUTER_LSA_SCHEDULE(oa) \
   do { \
-    if (! (oa)->thread_router_lsa) \
+    if (! (oa)->thread_router_lsa \
+        && CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
       (oa)->thread_router_lsa = \
         thread_add_event (master, ospf6_router_lsa_originate, oa, 0); \
   } while (0)
 #define OSPF6_NETWORK_LSA_SCHEDULE(oi) \
   do { \
-    if (! (oi)->thread_network_lsa) \
+    if (! (oi)->thread_network_lsa \
+        && ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
       (oi)->thread_network_lsa = \
         thread_add_event (master, ospf6_network_lsa_originate, oi, 0); \
   } while (0)
 #define OSPF6_LINK_LSA_SCHEDULE(oi) \
   do { \
-    if (! (oi)->thread_link_lsa) \
+    if (! (oi)->thread_link_lsa \
+        && ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
       (oi)->thread_link_lsa = \
         thread_add_event (master, ospf6_link_lsa_originate, oi, 0); \
   } while (0)
 #define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oa) \
   do { \
-    if (! (oa)->thread_intra_prefix_lsa) \
+    if (! (oa)->thread_intra_prefix_lsa \
+        && CHECK_FLAG((oa)->flag, OSPF6_AREA_ENABLE)) \
       (oa)->thread_intra_prefix_lsa = \
         thread_add_event (master, ospf6_intra_prefix_lsa_originate_stub, \
                           oa, 0); \
   } while (0)
 #define OSPF6_INTRA_PREFIX_LSA_SCHEDULE_TRANSIT(oi) \
   do { \
-    if (! (oi)->thread_intra_prefix_lsa) \
+    if (! (oi)->thread_intra_prefix_lsa \
+        && ! CHECK_FLAG((oi)->flag, OSPF6_INTERFACE_DISABLE)) \
       (oi)->thread_intra_prefix_lsa = \
         thread_add_event (master, ospf6_intra_prefix_lsa_originate_transit, \
                           oi, 0); \
@@ -200,6 +212,7 @@
 extern char *ospf6_network_lsdesc_lookup (u_int32_t router_id,
                                           struct ospf6_lsa *lsa);
 
+extern int ospf6_router_is_stub_router (struct ospf6_lsa *lsa);
 extern int ospf6_router_lsa_originate (struct thread *);
 extern int ospf6_network_lsa_originate (struct thread *);
 extern int ospf6_link_lsa_originate (struct thread *);
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index ff061df..4aa2b12 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -75,7 +75,9 @@
 {
   OSPF6_LSTYPE_UNKNOWN,
   "Unknown",
+  "Unk",
   ospf6_unknown_lsa_show,
+  NULL,
   OSPF6_LSA_DEBUG,
 };
 
@@ -118,6 +120,20 @@
   return buf;
 }
 
+const char *
+ospf6_lstype_short_name (u_int16_t type)
+{
+  static char buf[8];
+  struct ospf6_lsa_handler *handler;
+
+  handler = ospf6_get_lsa_handler (type);
+  if (handler && handler != &unknown_handler)
+    return handler->short_name;
+
+  snprintf (buf, sizeof (buf), "0x%04hx", ntohs (type));
+  return buf;
+}
+
 u_char
 ospf6_lstype_debug (u_int16_t type)
 {
@@ -139,11 +155,11 @@
 
   ospf6_lsa_age_current (lsa1);
   ospf6_lsa_age_current (lsa2);
-  if (ntohs (lsa1->header->age) == MAXAGE &&
-      ntohs (lsa2->header->age) != MAXAGE)
+  if (ntohs (lsa1->header->age) == OSPF_LSA_MAXAGE &&
+      ntohs (lsa2->header->age) != OSPF_LSA_MAXAGE)
     return 1;
-  if (ntohs (lsa1->header->age) != MAXAGE &&
-      ntohs (lsa2->header->age) == MAXAGE)
+  if (ntohs (lsa1->header->age) != OSPF_LSA_MAXAGE &&
+      ntohs (lsa2->header->age) == OSPF_LSA_MAXAGE)
     return 1;
 
   /* compare body */
@@ -218,19 +234,19 @@
     zlog_warn ("LSA: quagga_gettime failed, may fail LSA AGEs: %s",
                safe_strerror (errno));
 
-  if (ntohs (lsa->header->age) >= MAXAGE)
+  if (ntohs (lsa->header->age) >= OSPF_LSA_MAXAGE)
     {
       /* ospf6_lsa_premature_aging () sets age to MAXAGE; when using
          relative time, we cannot compare against lsa birth time, so
          we catch this special case here. */
-      lsa->header->age = htons (MAXAGE);
-      return MAXAGE;
+      lsa->header->age = htons (OSPF_LSA_MAXAGE);
+      return OSPF_LSA_MAXAGE;
     }
   /* calculate age */
   ulage = now.tv_sec - lsa->birth.tv_sec;
 
   /* if over MAXAGE, set to it */
-  age = (ulage > MAXAGE ? MAXAGE : ulage);
+  age = (ulage > OSPF_LSA_MAXAGE ? OSPF_LSA_MAXAGE : ulage);
 
   lsa->header->age = htons (age);
   return age;
@@ -243,8 +259,8 @@
   unsigned short age;
 
   age = ospf6_lsa_age_current (lsa) + transdelay;
-  if (age > MAXAGE)
-    age = MAXAGE;
+  if (age > OSPF_LSA_MAXAGE)
+    age = OSPF_LSA_MAXAGE;
   lsa->header->age = htons (age);
 }
 
@@ -258,7 +274,30 @@
   THREAD_OFF (lsa->expire);
   THREAD_OFF (lsa->refresh);
 
-  lsa->header->age = htons (MAXAGE);
+  /*
+   * We clear the LSA from the neighbor retx lists now because it
+   * will not get deleted later. Essentially, changing the age to
+   * MaxAge will prevent this LSA from being matched with its
+   * existing entries in the retx list thereby causing those entries
+   * to be silently replaced with its MaxAged version, but with ever
+   * increasing retx count causing this LSA to remain forever and
+   * for the MaxAge remover thread to be called forever too.
+   *
+   * The reason the previous entry silently disappears is that when
+   * entry is added to a neighbor's retx list, it replaces the existing
+   * entry. But since the ospf6_lsdb_add() routine is generic and not aware
+   * of the special semantics of retx count, the retx count is not
+   * decremented when its replaced. Attempting to add the incr and decr
+   * retx count routines as the hook_add and hook_remove for the retx lists
+   * have a problem because the hook_remove routine is called for MaxAge
+   * entries (as will be the case in a traditional LSDB, unlike in this case
+   * where an LSDB is used as an efficient tree structure to store all kinds
+   * of data) that are added instead of calling the hook_add routine.
+   */
+
+  ospf6_flood_clear (lsa);
+
+  lsa->header->age = htons (OSPF_LSA_MAXAGE);
   thread_execute (master, ospf6_lsa_expire, lsa, 0);
 }
 
@@ -297,15 +336,15 @@
   ageb = ospf6_lsa_age_current (b);
 
   /* MaxAge check */
-  if (agea == MAXAGE && ageb != MAXAGE)
+  if (agea == OSPF_LSA_MAXAGE && ageb != OSPF_LSA_MAXAGE)
     return -1;
-  else if (agea != MAXAGE && ageb == MAXAGE)
+  else if (agea != OSPF_LSA_MAXAGE && ageb == OSPF_LSA_MAXAGE)
     return 1;
 
   /* Age check */
-  if (agea > ageb && agea - ageb >= MAX_AGE_DIFF)
+  if (agea > ageb && agea - ageb >= OSPF_LSA_MAXAGE_DIFF)
     return 1;
-  else if (agea < ageb && ageb - agea >= MAX_AGE_DIFF)
+  else if (agea < ageb && ageb - agea >= OSPF_LSA_MAXAGE_DIFF)
     return -1;
 
   /* neither recent */
@@ -348,17 +387,19 @@
 void
 ospf6_lsa_show_summary_header (struct vty *vty)
 {
-  vty_out (vty, "%-12s %-15s %-15s %4s %8s %4s %4s %-8s%s",
+  vty_out (vty, "%-4s %-15s%-15s%4s %8s %30s%s",
            "Type", "LSId", "AdvRouter", "Age", "SeqNum",
-           "Cksm", "Len", "Duration", VNL);
+           "Payload", VNL);
 }
 
 void
 ospf6_lsa_show_summary (struct vty *vty, struct ospf6_lsa *lsa)
 {
   char adv_router[16], id[16];
-  struct timeval now, res;
-  char duration[16];
+  int type;
+  struct ospf6_lsa_handler *handler;
+  char buf[64], tmpbuf[80];
+  int cnt = 0;
 
   assert (lsa);
   assert (lsa->header);
@@ -367,16 +408,38 @@
   inet_ntop (AF_INET, &lsa->header->adv_router, adv_router,
              sizeof (adv_router));
 
-  quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
-  timersub (&now, &lsa->installed, &res);
-  timerstring (&res, duration, sizeof (duration));
+  type = ntohs(lsa->header->type);
+  handler = ospf6_get_lsa_handler (lsa->header->type);
+  if ((type == OSPF6_LSTYPE_INTER_PREFIX) ||
+      (type == OSPF6_LSTYPE_INTER_ROUTER) ||
+      (type == OSPF6_LSTYPE_AS_EXTERNAL))
+    {
+      vty_out (vty, "%-4s %-15s%-15s%4hu %8lx %30s%s",
+	       ospf6_lstype_short_name (lsa->header->type),
+	       id, adv_router, ospf6_lsa_age_current (lsa),
+	       (u_long) ntohl (lsa->header->seqnum),
+	       handler->get_prefix_str(lsa, buf, sizeof(buf), 0), VNL);
+    }
+  else if (type != OSPF6_LSTYPE_UNKNOWN)
+    {
+      sprintf (tmpbuf, "%-4s %-15s%-15s%4hu %8lx",
+	       ospf6_lstype_short_name (lsa->header->type),
+	       id, adv_router, ospf6_lsa_age_current (lsa),
+	       (u_long) ntohl (lsa->header->seqnum));
 
-  vty_out (vty, "%-12s %-15s %-15s %4hu %8lx %04hx %4hu %8s%s",
-           ospf6_lstype_name (lsa->header->type),
-           id, adv_router, ospf6_lsa_age_current (lsa),
-           (u_long) ntohl (lsa->header->seqnum),
-           ntohs (lsa->header->checksum), ntohs (lsa->header->length),
-           duration, VNL);
+      while (handler->get_prefix_str(lsa, buf, sizeof(buf), cnt) != NULL)
+	{
+	  vty_out (vty, "%s %30s%s", tmpbuf, buf, VNL);
+	  cnt++;
+	}
+    }
+  else
+    {
+      vty_out (vty, "%-4s %-15s%-15s%4hu %8lx%s",
+	       ospf6_lstype_short_name (lsa->header->type),
+	       id, adv_router, ospf6_lsa_age_current (lsa),
+	       (u_long) ntohl (lsa->header->seqnum), VNL);
+    }
 }
 
 void
@@ -427,8 +490,11 @@
   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
            ntohs (lsa->header->checksum),
            ntohs (lsa->header->length), VNL);
-  vty_out (vty, "    Prev: %p This: %p Next: %p%s",
-           lsa->prev, lsa, lsa->next, VNL);
+  vty_out (vty, "Flag: %x %s", lsa->flag, VNL);
+  vty_out (vty, "Lock: %d %s", lsa->lock, VNL);
+  vty_out (vty, "ReTx Count: %d%s", lsa->retrans_count, VNL);
+  vty_out (vty, "Threads: Expire: %x, Refresh: %x %s",
+	   lsa->expire, lsa->refresh, VNL);
   vty_out (vty, "%s", VNL);
   return;
 }
@@ -438,6 +504,8 @@
 {
   char adv_router[64], id[64];
   struct ospf6_lsa_handler *handler;
+  struct timeval now, res;
+  char duration[16];
 
   assert (lsa && lsa->header);
 
@@ -445,6 +513,10 @@
   inet_ntop (AF_INET, &lsa->header->adv_router,
              adv_router, sizeof (adv_router));
 
+  quagga_gettime (QUAGGA_CLK_MONOTONIC, &now);
+  timersub (&now, &lsa->installed, &res);
+  timerstring (&res, duration, sizeof (duration));
+
   vty_out (vty, "Age: %4hu Type: %s%s", ospf6_lsa_age_current (lsa),
            ospf6_lstype_name (lsa->header->type), VNL);
   vty_out (vty, "Link State ID: %s%s", id, VNL);
@@ -454,6 +526,7 @@
   vty_out (vty, "CheckSum: %#06hx Length: %hu%s",
            ntohs (lsa->header->checksum),
            ntohs (lsa->header->length), VNL);
+  vty_out (vty, "Duration: %s%s", duration, VNL);
 
   handler = ospf6_get_lsa_handler (lsa->header->type);
   if (handler->show == NULL)
@@ -558,6 +631,7 @@
   copy->received = lsa->received;
   copy->installed = lsa->installed;
   copy->lsdb = lsa->lsdb;
+  copy->rn = NULL;
 
   return copy;
 }
@@ -608,12 +682,12 @@
   if (CHECK_FLAG (lsa->flag, OSPF6_LSA_HEADERONLY))
     return 0;    /* dbexchange will do something ... */
 
-  /* reflood lsa */
-  ospf6_flood (NULL, lsa);
-
   /* reinstall lsa */
   ospf6_install_lsa (lsa);
 
+  /* reflood lsa */
+  ospf6_flood (NULL, lsa);
+
   /* schedule maxage remover */
   ospf6_maxage_remove (ospf6);
 
@@ -653,7 +727,7 @@
   new = ospf6_lsa_create (self->header);
   new->lsdb = old->lsdb;
   new->refresh = thread_add_timer (master, ospf6_lsa_refresh, new,
-                                   LS_REFRESH_TIME);
+                                   OSPF_LS_REFRESH_TIME);
 
   /* store it in the LSDB for self-originated LSAs */
   ospf6_lsdb_add (ospf6_lsa_copy (new), lsdb_self);
@@ -664,9 +738,8 @@
       ospf6_lsa_header_print (new);
     }
 
-  ospf6_flood_clear (old);
-  ospf6_flood (NULL, new);
   ospf6_install_lsa (new);
+  ospf6_flood (NULL, new);
 
   return 0;
 }
@@ -725,7 +798,7 @@
   unsigned int i; 
   unsigned int size = strlen (h->name);
 
-  if (!strcmp(h->name, "Unknown") &&
+  if (!strcmp(h->name, "unknown") &&
       h->type != OSPF6_LSTYPE_UNKNOWN)
     {
       snprintf (buf, sizeof (buf), "%#04hx", h->type);
@@ -745,7 +818,7 @@
 
 DEFUN (debug_ospf6_lsa_type,
        debug_ospf6_lsa_hex_cmd,
-       "debug ospf6 lsa XXXX/0xXXXX",
+       "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
        DEBUG_STR
        OSPF6_STR
        "Debug Link State Advertisements (LSAs)\n"
@@ -754,44 +827,21 @@
 {
   unsigned int i;
   struct ospf6_lsa_handler *handler = NULL;
-  unsigned long val;
-  char *endptr = NULL;
-  u_int16_t type = 0;
 
   assert (argc);
 
-  if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
-      (strlen (argv[0]) == 4))
-    {
-      val = strtoul (argv[0], &endptr, 16);
-      if (*endptr == '\0')
-        type = val;
-    }
-
   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
     {
       handler = vector_slot (ospf6_lsa_handler_vector, i);
       if (handler == NULL)
         continue;
-      if (type && handler->type == type)
+      if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
         break;
       if (! strcasecmp (argv[0], handler->name))
         break;
       handler = NULL;
     }
 
-  if (type && handler == NULL)
-    {
-      handler = (struct ospf6_lsa_handler *)
-        malloc (sizeof (struct ospf6_lsa_handler));
-      memset (handler, 0, sizeof (struct ospf6_lsa_handler));
-      handler->type = type;
-      handler->name = "Unknown";
-      handler->show = ospf6_unknown_lsa_show;
-      vector_set_index (ospf6_lsa_handler_vector,
-                        handler->type & OSPF6_LSTYPE_FCODE_MASK, handler);
-    }
-
   if (handler == NULL)
     handler = &unknown_handler;
 
@@ -799,7 +849,7 @@
     {
       if (! strcmp (argv[1], "originate"))
         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
-      if (! strcmp (argv[1], "examin"))
+      if (! strcmp (argv[1], "examine"))
         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
       if (! strcmp (argv[1], "flooding"))
         SET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
@@ -810,9 +860,18 @@
   return CMD_SUCCESS;
 }
 
+ALIAS (debug_ospf6_lsa_type,
+       debug_ospf6_lsa_hex_detail_cmd,
+       "debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown) (originate|examine|flooding)",
+       DEBUG_STR
+       OSPF6_STR
+       "Debug Link State Advertisements (LSAs)\n"
+       "Specify LS type as Hexadecimal\n"
+      )
+
 DEFUN (no_debug_ospf6_lsa_type,
        no_debug_ospf6_lsa_hex_cmd,
-       "no debug ospf6 lsa XXXX/0xXXXX",
+       "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix|unknown)",
        NO_STR
        DEBUG_STR
        OSPF6_STR
@@ -822,26 +881,15 @@
 {
   u_int i;
   struct ospf6_lsa_handler *handler = NULL;
-  unsigned long val;
-  char *endptr = NULL;
-  u_int16_t type = 0;
 
   assert (argc);
 
-  if ((strlen (argv[0]) == 6 && ! strncmp (argv[0], "0x", 2)) ||
-      (strlen (argv[0]) == 4))
-    {
-      val = strtoul (argv[0], &endptr, 16);
-      if (*endptr == '\0')
-        type = val;
-    }
-
   for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
     {
       handler = vector_slot (ospf6_lsa_handler_vector, i);
       if (handler == NULL)
         continue;
-      if (type && handler->type == type)
+      if (strncmp (argv[0], ospf6_lsa_handler_name(handler), strlen(argv[0])) == 0)
         break;
       if (! strcasecmp (argv[0], handler->name))
         break;
@@ -854,7 +902,7 @@
     {
       if (! strcmp (argv[1], "originate"))
         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_ORIGINATE);
-      if (! strcmp (argv[1], "examin"))
+      if (! strcmp (argv[1], "examine"))
         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN);
       if (! strcmp (argv[1], "flooding"))
         UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD);
@@ -862,120 +910,30 @@
   else
     UNSET_FLAG (handler->debug, OSPF6_LSA_DEBUG);
 
-  if (handler->debug == 0 &&
-      !strcmp(handler->name, "Unknown") && type != OSPF6_LSTYPE_UNKNOWN)
-    {
-      free (handler);
-      vector_slot (ospf6_lsa_handler_vector, i) = NULL;
-    }
-
   return CMD_SUCCESS;
 }
 
-struct cmd_element debug_ospf6_lsa_type_cmd;
-struct cmd_element debug_ospf6_lsa_type_detail_cmd;
-struct cmd_element no_debug_ospf6_lsa_type_cmd;
-struct cmd_element no_debug_ospf6_lsa_type_detail_cmd;
+ALIAS (no_debug_ospf6_lsa_type,
+       no_debug_ospf6_lsa_hex_detail_cmd,
+       "no debug ospf6 lsa (router|network|inter-prefix|inter-router|as-ext|grp-mbr|type7|link|intra-prefix) (originate|examine|flooding)",
+       NO_STR
+       DEBUG_STR
+       OSPF6_STR
+       "Debug Link State Advertisements (LSAs)\n"
+       "Specify LS type as Hexadecimal\n"
+      )
 
 void
 install_element_ospf6_debug_lsa (void)
 {
-  u_int i;
-  struct ospf6_lsa_handler *handler;
-#define STRSIZE  256
-#define DOCSIZE  1024
-  static char strbuf[STRSIZE];
-  static char docbuf[DOCSIZE];
-  static char detail_strbuf[STRSIZE];
-  static char detail_docbuf[DOCSIZE];
-  char *str, *no_str;
-  char *doc, *no_doc;
-
-  strbuf[0] = '\0';
-  no_str = &strbuf[strlen (strbuf)];
-  strncat (strbuf, "no ", STRSIZE - strlen (strbuf));
-  str = &strbuf[strlen (strbuf)];
-
-  strncat (strbuf, "debug ospf6 lsa (", STRSIZE - strlen (strbuf));
-  for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
-    {
-      handler = vector_slot (ospf6_lsa_handler_vector, i);
-      if (handler == NULL)
-        continue;
-      strncat (strbuf, ospf6_lsa_handler_name (handler),
-               STRSIZE - strlen (strbuf));
-      strncat (strbuf, "|", STRSIZE - strlen (strbuf));
-    }
-  strbuf[strlen (strbuf) - 1] = ')';
-  strbuf[strlen (strbuf)] = '\0';
-
-  docbuf[0] = '\0';
-  no_doc = &docbuf[strlen (docbuf)];
-  strncat (docbuf, NO_STR, DOCSIZE - strlen (docbuf));
-  doc = &docbuf[strlen (docbuf)];
-
-  strncat (docbuf, DEBUG_STR, DOCSIZE - strlen (docbuf));
-  strncat (docbuf, OSPF6_STR, DOCSIZE - strlen (docbuf));
-  strncat (docbuf, "Debug Link State Advertisements (LSAs)\n",
-           DOCSIZE - strlen (docbuf));
-
-  for (i = 0; i < vector_active (ospf6_lsa_handler_vector); i++)
-    {
-      handler = vector_slot (ospf6_lsa_handler_vector, i);
-      if (handler == NULL)
-        continue;
-      strncat (docbuf, "Debug ", DOCSIZE - strlen (docbuf));
-      strncat (docbuf, handler->name, DOCSIZE - strlen (docbuf));
-      strncat (docbuf, "-LSA\n", DOCSIZE - strlen (docbuf));
-    }
-  docbuf[strlen (docbuf)] = '\0';
-
-  debug_ospf6_lsa_type_cmd.string = str;
-  debug_ospf6_lsa_type_cmd.func = debug_ospf6_lsa_type;
-  debug_ospf6_lsa_type_cmd.doc = doc;
-
-  no_debug_ospf6_lsa_type_cmd.string = no_str;
-  no_debug_ospf6_lsa_type_cmd.func = no_debug_ospf6_lsa_type;
-  no_debug_ospf6_lsa_type_cmd.doc = no_doc;
-
-  strncpy (detail_strbuf, strbuf, STRSIZE);
-  strncat (detail_strbuf, " (originate|examin|flooding)",
-           STRSIZE - strlen (detail_strbuf));
-  detail_strbuf[strlen (detail_strbuf)] = '\0';
-  no_str = &detail_strbuf[0];
-  str = &detail_strbuf[strlen ("no ")];
-
-  strncpy (detail_docbuf, docbuf, DOCSIZE);
-  strncat (detail_docbuf, "Debug Originating LSA\n",
-           DOCSIZE - strlen (detail_docbuf));
-  strncat (detail_docbuf, "Debug Examining LSA\n",
-           DOCSIZE - strlen (detail_docbuf));
-  strncat (detail_docbuf, "Debug Flooding LSA\n",
-           DOCSIZE - strlen (detail_docbuf));
-  detail_docbuf[strlen (detail_docbuf)] = '\0';
-  no_doc = &detail_docbuf[0];
-  doc = &detail_docbuf[strlen (NO_STR)];
-
-  debug_ospf6_lsa_type_detail_cmd.string = str;
-  debug_ospf6_lsa_type_detail_cmd.func = debug_ospf6_lsa_type;
-  debug_ospf6_lsa_type_detail_cmd.doc = doc;
-
-  no_debug_ospf6_lsa_type_detail_cmd.string = no_str;
-  no_debug_ospf6_lsa_type_detail_cmd.func = no_debug_ospf6_lsa_type;
-  no_debug_ospf6_lsa_type_detail_cmd.doc = no_doc;
-
   install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_cmd);
-  install_element (ENABLE_NODE, &debug_ospf6_lsa_type_cmd);
-  install_element (ENABLE_NODE, &debug_ospf6_lsa_type_detail_cmd);
+  install_element (ENABLE_NODE, &debug_ospf6_lsa_hex_detail_cmd);
   install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_cmd);
-  install_element (ENABLE_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
+  install_element (ENABLE_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
   install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_lsa_type_cmd);
-  install_element (CONFIG_NODE, &debug_ospf6_lsa_type_detail_cmd);
+  install_element (CONFIG_NODE, &debug_ospf6_lsa_hex_detail_cmd);
   install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_cmd);
-  install_element (CONFIG_NODE, &no_debug_ospf6_lsa_type_detail_cmd);
+  install_element (CONFIG_NODE, &no_debug_ospf6_lsa_hex_detail_cmd);
 }
 
 int
@@ -996,7 +954,7 @@
         vty_out (vty, "debug ospf6 lsa %s originate%s",
                  ospf6_lsa_handler_name (handler), VNL);
       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_EXAMIN))
-        vty_out (vty, "debug ospf6 lsa %s examin%s",
+        vty_out (vty, "debug ospf6 lsa %s examine%s",
                  ospf6_lsa_handler_name (handler), VNL);
       if (CHECK_FLAG (handler->debug, OSPF6_LSA_DEBUG_FLOOD))
         vty_out (vty, "debug ospf6 lsa %s flooding%s",
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index 263411f..aed89df 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -107,15 +107,16 @@
   ((L)->header->adv_router == (a) && (L)->header->id == (i) && \
    (L)->header->type == (t))
 #define OSPF6_LSA_IS_DIFFER(L1, L2)  ospf6_lsa_is_differ (L1, L2)
-#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == MAXAGE)
+#define OSPF6_LSA_IS_MAXAGE(L) (ospf6_lsa_age_current (L) == OSPF_LSA_MAXAGE)
 #define OSPF6_LSA_IS_CHANGED(L1, L2) ospf6_lsa_is_changed (L1, L2)
+#define OSPF6_LSA_IS_SEQWRAP(L) ((L)->header->seqnum == htonl(OSPF_MAX_SEQUENCE_NUMBER + 1))
+
 
 struct ospf6_lsa
 {
   char              name[64];   /* dump string */
 
-  struct ospf6_lsa *prev;
-  struct ospf6_lsa *next;
+  struct route_node *rn;
 
   unsigned char     lock;           /* reference counter */
   unsigned char     flag;           /* special meaning (e.g. floodback) */
@@ -140,12 +141,15 @@
 #define OSPF6_LSA_FLOODBACK  0x02
 #define OSPF6_LSA_DUPLICATE  0x04
 #define OSPF6_LSA_IMPLIEDACK 0x08
+#define OSPF6_LSA_SEQWRAPPED 0x20
 
 struct ospf6_lsa_handler
 {
   u_int16_t type; /* host byte order */
   const char *name;
+  const char *short_name;
   int (*show) (struct vty *, struct ospf6_lsa *);
+  char *(*get_prefix_str) (struct ospf6_lsa *, char *buf, int buflen, int pos);
   u_char debug;
 };
 
@@ -208,6 +212,7 @@
 
 /* Function Prototypes */
 extern const char *ospf6_lstype_name (u_int16_t type);
+extern const char *ospf6_lstype_short_name (u_int16_t type);
 extern u_char ospf6_lstype_debug (u_int16_t type);
 extern int ospf6_lsa_is_differ (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
 extern int ospf6_lsa_is_changed (struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2);
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index 280bdf9..707afc6 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -54,9 +54,12 @@
 void
 ospf6_lsdb_delete (struct ospf6_lsdb *lsdb)
 {
-  ospf6_lsdb_remove_all (lsdb);
-  route_table_finish (lsdb->table);
-  XFREE (MTYPE_OSPF6_LSDB, lsdb);
+  if (lsdb != NULL)
+    {
+      ospf6_lsdb_remove_all (lsdb);
+      route_table_finish (lsdb->table);
+      XFREE (MTYPE_OSPF6_LSDB, lsdb);
+    }
 }
 
 static void
@@ -70,7 +73,7 @@
   key->prefixlen += len * 8;
 }
 
-#ifndef NDEBUG
+#ifdef DEBUG
 static void
 _lsdb_count_assert (struct ospf6_lsdb *lsdb)
 {
@@ -94,16 +97,16 @@
   assert (num == lsdb->count);
 }
 #define ospf6_lsdb_count_assert(t) (_lsdb_count_assert (t))
-#else /*NDEBUG*/
+#else /*DEBUG*/
 #define ospf6_lsdb_count_assert(t) ((void) 0)
-#endif /*NDEBUG*/
+#endif /*DEBUG*/
 
 void
 ospf6_lsdb_add (struct ospf6_lsa *lsa, struct ospf6_lsdb *lsdb)
 {
   struct prefix_ipv6 key;
-  struct route_node *current, *nextnode, *prevnode;
-  struct ospf6_lsa *next, *prev, *old = NULL;
+  struct route_node *current;
+  struct ospf6_lsa *old = NULL;
 
   memset (&key, 0, sizeof (key));
   ospf6_lsdb_set_key (&key, &lsa->header->type, sizeof (lsa->header->type));
@@ -114,56 +117,26 @@
   current = route_node_get (lsdb->table, (struct prefix *) &key);
   old = current->info;
   current->info = lsa;
+  lsa->rn = current;
   ospf6_lsa_lock (lsa);
 
-  if (old)
+  if (!old)
     {
-      if (old->prev)
-        old->prev->next = lsa;
-      if (old->next)
-        old->next->prev = lsa;
-      lsa->next = old->next;
-      lsa->prev = old->prev;
+      lsdb->count++;
+
+      if (OSPF6_LSA_IS_MAXAGE (lsa))
+	{
+	  if (lsdb->hook_remove)
+	    (*lsdb->hook_remove) (lsa);
+	}
+      else
+	{
+	  if (lsdb->hook_add)
+	    (*lsdb->hook_add) (lsa);
+	}
     }
   else
     {
-      /* next link */
-      nextnode = current;
-      route_lock_node (nextnode);
-      do {
-        nextnode = route_next (nextnode);
-      } while (nextnode && nextnode->info == NULL);
-      if (nextnode == NULL)
-        lsa->next = NULL;
-      else
-        {
-          next = nextnode->info;
-          lsa->next = next;
-          next->prev = lsa;
-          route_unlock_node (nextnode);
-        }
-
-      /* prev link */
-      prevnode = current;
-      route_lock_node (prevnode);
-      do {
-        prevnode = route_prev (prevnode);
-      } while (prevnode && prevnode->info == NULL);
-      if (prevnode == NULL)
-        lsa->prev = NULL;
-      else
-        {
-          prev = prevnode->info;
-          lsa->prev = prev;
-          prev->next = lsa;
-          route_unlock_node (prevnode);
-        }
-
-      lsdb->count++;
-    }
-
-  if (old)
-    {
       if (OSPF6_LSA_IS_CHANGED (old, lsa))
         {
           if (OSPF6_LSA_IS_MAXAGE (lsa))
@@ -187,20 +160,8 @@
                 (*lsdb->hook_add) (lsa);
             }
         }
+      ospf6_lsa_unlock (old);
     }
-  else if (OSPF6_LSA_IS_MAXAGE (lsa))
-    {
-      if (lsdb->hook_remove)
-        (*lsdb->hook_remove) (lsa);
-    }
-  else
-    {
-      if (lsdb->hook_add)
-        (*lsdb->hook_add) (lsa);
-    }
-
-  if (old)
-    ospf6_lsa_unlock (old);
 
   ospf6_lsdb_count_assert (lsdb);
 }
@@ -220,19 +181,15 @@
   node = route_node_lookup (lsdb->table, (struct prefix *) &key);
   assert (node && node->info == lsa);
 
-  if (lsa->prev)
-    lsa->prev->next = lsa->next;
-  if (lsa->next)
-    lsa->next->prev = lsa->prev;
-
   node->info = NULL;
   lsdb->count--;
 
   if (lsdb->hook_remove)
     (*lsdb->hook_remove) (lsa);
 
+  route_unlock_node (node);	/* to free the lookup lock */
+  route_unlock_node (node);	/* to free the original lock */
   ospf6_lsa_unlock (lsa);
-  route_unlock_node (node);
 
   ospf6_lsdb_count_assert (lsdb);
 }
@@ -255,6 +212,8 @@
   node = route_node_lookup (lsdb->table, (struct prefix *) &key);
   if (node == NULL || node->info == NULL)
     return NULL;
+
+  route_unlock_node (node);
   return (struct ospf6_lsa *) node->info;
 }
 
@@ -306,21 +265,9 @@
 
   if (prefix_same (&node->p, p))
     {
-      struct route_node *prev = node;
-      struct ospf6_lsa *lsa_prev;
-      struct ospf6_lsa *lsa_next;
-
       node = route_next (node);
       while (node && node->info == NULL)
         node = route_next (node);
-
-      lsa_prev = prev->info;
-      lsa_next = (node ? node->info : NULL);
-      assert (lsa_prev);
-      assert (lsa_prev->next == lsa_next);
-      if (lsa_next)
-        assert (lsa_next->prev == lsa_prev);
-      zlog_debug ("lsdb_lookup_next: assert OK with previous LSA");
     }
 
   if (! node)
@@ -346,7 +293,6 @@
   if (node == NULL)
     return NULL;
 
-  route_unlock_node (node);
   if (node->info)
     ospf6_lsa_lock ((struct ospf6_lsa *) node->info);
   return (struct ospf6_lsa *) node->info;
@@ -355,12 +301,20 @@
 struct ospf6_lsa *
 ospf6_lsdb_next (struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsa *next = lsa->next;
+  struct route_node *node = lsa->rn;
+  struct ospf6_lsa *next = NULL;
+
+  do {
+    node = route_next (node);
+  } while (node && node->info == NULL);
+
+  if ((node != NULL) && (node->info != NULL))
+    {
+      next = node->info;
+      ospf6_lsa_lock (next);
+    }
 
   ospf6_lsa_unlock (lsa);
-  if (next)
-    ospf6_lsa_lock (next);
-
   return next;
 }
 
@@ -390,8 +344,6 @@
 
   if (node == NULL)
     return NULL;
-  else
-    route_unlock_node (node);
 
   if (! prefix_match ((struct prefix *) &key, &node->p))
     return NULL;
@@ -406,18 +358,19 @@
 ospf6_lsdb_type_router_next (u_int16_t type, u_int32_t adv_router,
                              struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsa *next = lsa->next;
+  struct ospf6_lsa *next = ospf6_lsdb_next(lsa);
 
   if (next)
     {
       if (next->header->type != type ||
           next->header->adv_router != adv_router)
-        next = NULL;
+	{
+	  route_unlock_node (next->rn);
+	  ospf6_lsa_unlock (next);
+	  next = NULL;
+	}
     }
 
-  if (next)
-    ospf6_lsa_lock (next);
-  ospf6_lsa_unlock (lsa);
   return next;
 }
 
@@ -444,8 +397,6 @@
 
   if (node == NULL)
     return NULL;
-  else
-    route_unlock_node (node);
 
   if (! prefix_match ((struct prefix *) &key, &node->p))
     return NULL;
@@ -459,17 +410,18 @@
 struct ospf6_lsa *
 ospf6_lsdb_type_next (u_int16_t type, struct ospf6_lsa *lsa)
 {
-  struct ospf6_lsa *next = lsa->next;
+  struct ospf6_lsa *next = ospf6_lsdb_next (lsa);
 
   if (next)
     {
       if (next->header->type != type)
-        next = NULL;
+	{
+	  route_unlock_node (next->rn);
+	  ospf6_lsa_unlock (next);
+	  next = NULL;
+	}
     }
 
-  if (next)
-    ospf6_lsa_lock (next);
-  ospf6_lsa_unlock (lsa);
   return next;
 }
 
@@ -477,11 +429,62 @@
 ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb)
 {
   struct ospf6_lsa *lsa;
+
+  if (lsdb == NULL)
+    return;
+
   for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
     ospf6_lsdb_remove (lsa, lsdb);
 }
 
 void
+ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa)
+{
+  if (lsa != NULL)
+    {
+      if (lsa->rn != NULL)
+	route_unlock_node (lsa->rn);
+      ospf6_lsa_unlock (lsa);
+    }
+}
+
+int
+ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb)
+{
+  int reschedule = 0;
+  struct ospf6_lsa *lsa;
+
+  for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa))
+    {
+      if (! OSPF6_LSA_IS_MAXAGE (lsa))
+	continue;
+      if (lsa->retrans_count != 0)
+	{
+	  reschedule = 1;
+	  continue;
+	}
+      if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))
+	zlog_debug ("Remove MaxAge %s", lsa->name);
+      if (CHECK_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED))
+      {
+        UNSET_FLAG(lsa->flag, OSPF6_LSA_SEQWRAPPED);
+        /*
+         * lsa->header->age = 0;
+         */
+        lsa->header->seqnum = htonl(OSPF_MAX_SEQUENCE_NUMBER + 1);
+        ospf6_lsa_checksum (lsa->header);
+
+	THREAD_OFF(lsa->refresh);
+        thread_execute (master, ospf6_lsa_refresh, lsa, 0);
+      } else {
+        ospf6_lsdb_remove (lsa, lsdb);
+      }
+    }
+
+  return (reschedule);
+}
+
+void
 ospf6_lsdb_show (struct vty *vty, int level,
                  u_int16_t *type, u_int32_t *id, u_int32_t *adv_router,
                  struct ospf6_lsdb *lsdb)
@@ -551,7 +554,7 @@
         continue;
       if (ntohl (lsa->header->id) > id)
       {
-        ospf6_lsa_unlock (lsa);
+	ospf6_lsdb_lsa_unlock (lsa);
         break;
       }
       id++;
@@ -572,7 +575,7 @@
   /* if current database copy not found, return InitialSequenceNumber */
   lsa = ospf6_lsdb_lookup (type, id, adv_router, lsdb);
   if (lsa == NULL)
-    seqnum = INITIAL_SEQUENCE_NUMBER;
+    seqnum = OSPF_INITIAL_SEQUENCE_NUMBER;
   else
     seqnum = (signed long) ntohl (lsa->header->seqnum) + 1;
 
diff --git a/ospf6d/ospf6_lsdb.h b/ospf6d/ospf6_lsdb.h
index 71297da..a124adb 100644
--- a/ospf6d/ospf6_lsdb.h
+++ b/ospf6d/ospf6_lsdb.h
@@ -34,21 +34,6 @@
   void (*hook_remove) (struct ospf6_lsa *);
 };
 
-#define OSPF6_LSDB_MAXAGE_REMOVER(lsdb)                                  \
-  do {                                                                   \
-    struct ospf6_lsa *lsa;                                               \
-    for (lsa = ospf6_lsdb_head (lsdb); lsa; lsa = ospf6_lsdb_next (lsa)) \
-      {                                                                  \
-        if (! OSPF6_LSA_IS_MAXAGE (lsa))                                 \
-          continue;                                                      \
-        if (lsa->retrans_count != 0)                                     \
-          continue;                                                      \
-        if (IS_OSPF6_DEBUG_LSA_TYPE (lsa->header->type))                 \
-          zlog_debug ("Remove MaxAge %s", lsa->name);                    \
-        ospf6_lsdb_remove (lsa, lsdb);                                   \
-      }                                                                  \
-  } while (0)
-
 /* Function Prototypes */
 extern struct ospf6_lsdb *ospf6_lsdb_create (void *data);
 extern void ospf6_lsdb_delete (struct ospf6_lsdb *lsdb);
@@ -79,6 +64,7 @@
                                                struct ospf6_lsa *lsa);
 
 extern void ospf6_lsdb_remove_all (struct ospf6_lsdb *lsdb);
+extern void ospf6_lsdb_lsa_unlock (struct ospf6_lsa *lsa);
 
 #define OSPF6_LSDB_SHOW_LEVEL_NORMAL   0
 #define OSPF6_LSDB_SHOW_LEVEL_DETAIL   1
@@ -94,5 +80,6 @@
 extern u_int32_t ospf6_new_ls_seqnum (u_int16_t type, u_int32_t id,
                                       u_int32_t adv_router,
                                       struct ospf6_lsdb *lsdb);
+extern int ospf6_lsdb_maxage_remover (struct ospf6_lsdb *lsdb);
 
 #endif /* OSPF6_LSDB_H */
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 17d7654..e991971 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -41,6 +41,8 @@
 #include "ospf6_message.h"
 #include "ospf6_asbr.h"
 #include "ospf6_lsa.h"
+#include "ospf6_interface.h"
+#include "ospf6_zebra.h"
 
 /* Default configuration file name for ospf6d. */
 #define OSPF6_DEFAULT_CONFIG       "ospf6d.conf"
@@ -134,12 +136,16 @@
 static void __attribute__ ((noreturn))
 ospf6_exit (int status)
 {
-  extern struct ospf6 *ospf6;
-  extern struct zclient *zclient;
+  struct listnode *node;
+  struct interface *ifp;
 
   if (ospf6)
     ospf6_delete (ospf6);
 
+  for (ALL_LIST_ELEMENTS_RO(iflist, node, ifp))
+    if (ifp->info != NULL)
+      ospf6_interface_delete(ifp->info);
+
   ospf6_message_terminate ();
   ospf6_asbr_terminate ();
   ospf6_lsa_terminate ();
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 5edb70c..5fb5a21 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -517,20 +517,20 @@
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
             zlog_debug ("Add request (No database copy)");
-          ospf6_lsdb_add (his, on->request_list);
+          ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
         }
       else if (ospf6_lsa_compare (his, mine) < 0)
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
             zlog_debug ("Add request (Received MoreRecent)");
-          ospf6_lsdb_add (his, on->request_list);
+          ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
         }
       else
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
             zlog_debug ("Discard (Existing MoreRecent)");
-          ospf6_lsa_delete (his);
         }
+      ospf6_lsa_delete (his);
     }
 
   assert (p == OSPF6_MESSAGE_END (oh));
@@ -539,7 +539,7 @@
   on->dbdesc_seqnum ++;
 
   /* schedule send lsreq */
-  if (on->thread_send_lsreq == NULL)
+  if (on->request_list->count && (on->thread_send_lsreq == NULL))
     on->thread_send_lsreq =
       thread_add_event (master, ospf6_lsreq_send, on, 0);
 
@@ -735,10 +735,9 @@
         {
           if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
             zlog_debug ("Add request-list: %s", his->name);
-          ospf6_lsdb_add (his, on->request_list);
+          ospf6_lsdb_add (ospf6_lsa_copy(his), on->request_list);
         }
-      else
-        ospf6_lsa_delete (his);
+      ospf6_lsa_delete (his);
     }
 
   assert (p == OSPF6_MESSAGE_END (oh));
@@ -747,7 +746,8 @@
   on->dbdesc_seqnum = ntohl (dbdesc->seqnum);
 
   /* schedule send lsreq */
-  if (on->thread_send_lsreq == NULL)
+  if ((on->thread_send_lsreq == NULL) &&
+      (on->request_list->count))
     on->thread_send_lsreq =
       thread_add_event (master, ospf6_lsreq_send, on, 0);
 
@@ -1282,7 +1282,7 @@
   {
     if (IS_OSPF6_DEBUG_MESSAGE (oh->type, RECV))
     {
-      if (oh->area_id == BACKBONE_AREA_ID)
+      if (oh->area_id == OSPF_AREA_BACKBONE)
         zlog_debug ("%s: Message may be via Virtual Link: not supported", __func__);
       else
         zlog_debug
@@ -1351,19 +1351,6 @@
 
   assert (p == OSPF6_MESSAGE_END (oh));
 
-  /* RFC2328 Section 10.9: When the neighbor responds to these requests
-     with the proper Link State Update packet(s), the Link state request
-     list is truncated and a new Link State Request packet is sent. */
-  /* send new Link State Request packet if this LS Update packet
-     can be recognized as a response to our previous LS Request */
-  if (! IN6_IS_ADDR_MULTICAST (dst) &&
-      (on->state == OSPF6_NEIGHBOR_EXCHANGE ||
-       on->state == OSPF6_NEIGHBOR_LOADING))
-    {
-      THREAD_OFF (on->thread_send_lsreq);
-      on->thread_send_lsreq =
-        thread_add_event (master, ospf6_lsreq_send, on, 0);
-    }
 }
 
 static void
@@ -1556,7 +1543,7 @@
     }
 
   oi = ospf6_interface_lookup_by_ifindex (ifindex);
-  if (oi == NULL || oi->area == NULL)
+  if (oi == NULL || oi->area == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
     {
       zlog_debug ("Message received on disabled interface");
       return 0;
@@ -1785,6 +1772,7 @@
   struct ospf6_dbdesc *dbdesc;
   u_char *p;
   struct ospf6_lsa *lsa;
+  struct in6_addr *dst;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_dbdesc = (struct thread *) NULL;
@@ -1809,7 +1797,8 @@
                                    sizeof (struct ospf6_header));
 
   /* if this is initial one, initialize sequence number for DbDesc */
-  if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT))
+  if (CHECK_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT) &&
+      (on->dbdesc_seqnum == 0))
     {
       struct timeval tv;
       if (quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv) < 0)
@@ -1837,7 +1826,7 @@
           if (p - sendbuf + sizeof (struct ospf6_lsa_header) >
               ospf6_packet_max(on->ospf6_if))
             {
-              ospf6_lsa_unlock (lsa);
+              ospf6_lsdb_lsa_unlock (lsa);
               break;
             }
           memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@@ -1848,8 +1837,14 @@
   oh->type = OSPF6_MESSAGE_TYPE_DBDESC;
   oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
+
+  if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+    dst = &allspfrouters6;
+  else
+    dst = &on->linklocal_addr;
+
+  ospf6_send (on->ospf6_if->linklocal_addr, dst, on->ospf6_if, oh);
+
   return 0;
 }
 
@@ -1871,7 +1866,7 @@
     {
       if (size + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
         {
-          ospf6_lsa_unlock (lsa);
+          ospf6_lsdb_lsa_unlock (lsa);
           break;
         }
 
@@ -1900,7 +1895,7 @@
   struct ospf6_header *oh;
   struct ospf6_lsreq_entry *e;
   u_char *p;
-  struct ospf6_lsa *lsa;
+  struct ospf6_lsa *lsa, *last_req;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_lsreq = (struct thread *) NULL;
@@ -1922,13 +1917,9 @@
       return 0;
     }
 
-  /* set next thread */
-  on->thread_send_lsreq =
-    thread_add_timer (master, ospf6_lsreq_send, on,
-                      on->ospf6_if->rxmt_interval);
-
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
+  last_req = NULL;
 
   /* set Request entries in lsreq */
   p = (u_char *)((caddr_t) oh + sizeof (struct ospf6_header));
@@ -1938,7 +1929,7 @@
       /* MTU check */
       if (p - sendbuf + sizeof (struct ospf6_lsreq_entry) > ospf6_packet_max(on->ospf6_if))
         {
-          ospf6_lsa_unlock (lsa);
+          ospf6_lsdb_lsa_unlock (lsa);
           break;
         }
 
@@ -1947,13 +1938,37 @@
       e->id = lsa->header->id;
       e->adv_router = lsa->header->adv_router;
       p += sizeof (struct ospf6_lsreq_entry);
+      last_req = lsa;
+    }
+
+  if (last_req != NULL)
+    {
+      if (on->last_ls_req != NULL)
+	{
+	  ospf6_lsa_unlock (on->last_ls_req);
+	}
+      ospf6_lsa_lock (last_req);
+      on->last_ls_req = last_req;
     }
 
   oh->type = OSPF6_MESSAGE_TYPE_LSREQ;
   oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+  if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+    ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
               on->ospf6_if, oh);
+  else
+    ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		on->ospf6_if, oh);
+
+  /* set next thread */
+  if (on->request_list->count != 0)
+    {
+      on->thread_send_lsreq =
+	thread_add_timer (master, ospf6_lsreq_send, on,
+			  on->ospf6_if->rxmt_interval);
+    }
+
   return 0;
 }
 
@@ -1964,7 +1979,7 @@
   struct ospf6_header *oh;
   struct ospf6_lsupdate *lsupdate;
   u_char *p;
-  int num;
+  int lsa_cnt;
   struct ospf6_lsa *lsa;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
@@ -1981,22 +1996,13 @@
       return 0;
     }
 
-  /* if we have nothing to send, return */
-  if (on->lsupdate_list->count == 0 &&
-      on->retrans_list->count == 0)
-    {
-      if (IS_OSPF6_DEBUG_MESSAGE (OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
-        zlog_debug ("Quit to send (nothing to send)");
-      return 0;
-    }
-
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
   lsupdate = (struct ospf6_lsupdate *)
     ((caddr_t) oh + sizeof (struct ospf6_header));
 
   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
-  num = 0;
+  lsa_cnt = 0;
 
   /* lsupdate_list lists those LSA which doesn't need to be
      retransmitted. remove those from the list */
@@ -2005,58 +2011,85 @@
     {
       /* MTU check */
       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
-          > ospf6_packet_max(on->ospf6_if))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(on->ospf6_if))
+	{
+	  ospf6_lsdb_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, on->lsupdate_list);
     }
 
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
+      lsupdate->lsa_number = htonl (lsa_cnt);
+
+      if ((on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (on->ospf6_if->state == OSPF6_INTERFACE_DR) ||
+	  (on->ospf6_if->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
+		    on->ospf6_if, oh);
+      else
+	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		    on->ospf6_if, oh);
+    }
+
+  /* The addresses used for retransmissions are different from those sent the
+     first time and so we need to separate them here.
+  */
+  memset (sendbuf, 0, iobuflen);
+  oh = (struct ospf6_header *) sendbuf;
+  lsupdate = (struct ospf6_lsupdate *)
+    ((caddr_t) oh + sizeof (struct ospf6_header));
+  p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
+  lsa_cnt = 0;
+
   for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
       /* MTU check */
       if ( (p - sendbuf + (unsigned int)OSPF6_LSA_SIZE (lsa->header))
-          > ospf6_packet_max(on->ospf6_if))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(on->ospf6_if))
+	{
+	  ospf6_lsdb_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
     }
 
-  lsupdate->lsa_number = htonl (num);
-
-  oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
-  oh->length = htons (p - sendbuf);
-
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
-
-  if (on->lsupdate_list->count != 0 ||
-      on->retrans_list->count != 0)
+  if (lsa_cnt)
     {
-      if (on->lsupdate_list->count != 0)
-        on->thread_send_lsupdate =
-          thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
+      lsupdate->lsa_number = htonl (lsa_cnt);
+
+      if (on->ospf6_if->state == OSPF6_INTERFACE_POINTTOPOINT)
+	ospf6_send (on->ospf6_if->linklocal_addr, &allspfrouters6,
+		    on->ospf6_if, oh);
       else
-        on->thread_send_lsupdate =
-          thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
-                            on->ospf6_if->rxmt_interval);
+	ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		    on->ospf6_if, oh);
     }
 
+  if (on->lsupdate_list->count != 0)
+    on->thread_send_lsupdate =
+      thread_add_event (master, ospf6_lsupdate_send_neighbor, on, 0);
+  else if (on->retrans_list->count != 0)
+    on->thread_send_lsupdate =
+      thread_add_timer (master, ospf6_lsupdate_send_neighbor, on,
+			on->ospf6_if->rxmt_interval);
   return 0;
 }
 
@@ -2067,7 +2100,7 @@
   struct ospf6_header *oh;
   struct ospf6_lsupdate *lsupdate;
   u_char *p;
-  int num;
+  int lsa_cnt;
   struct ospf6_lsa *lsa;
 
   oi = (struct ospf6_interface *) THREAD_ARG (thread);
@@ -2088,41 +2121,46 @@
   memset (sendbuf, 0, iobuflen);
   oh = (struct ospf6_header *) sendbuf;
   lsupdate = (struct ospf6_lsupdate *)((caddr_t) oh +
-                                       sizeof (struct ospf6_header));
+				       sizeof (struct ospf6_header));
 
   p = (u_char *)((caddr_t) lsupdate + sizeof (struct ospf6_lsupdate));
-  num = 0;
+  lsa_cnt = 0;
 
   for (lsa = ospf6_lsdb_head (oi->lsupdate_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     {
       /* MTU check */
       if ( (p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE (lsa->header)))
-          > ospf6_packet_max(oi))
-        {
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	   > ospf6_packet_max(oi))
+	{
+	  ospf6_lsdb_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
       memcpy (p, lsa->header, OSPF6_LSA_SIZE (lsa->header));
       p += OSPF6_LSA_SIZE (lsa->header);
-      num++;
+      lsa_cnt++;
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, oi->lsupdate_list);
     }
 
-  lsupdate->lsa_number = htonl (num);
+  if (lsa_cnt)
+    {
+      lsupdate->lsa_number = htonl (lsa_cnt);
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
-  oh->length = htons (p - sendbuf);
+      oh->type = OSPF6_MESSAGE_TYPE_LSUPDATE;
+      oh->length = htons (p - sendbuf);
 
-  if (oi->state == OSPF6_INTERFACE_DR ||
-      oi->state == OSPF6_INTERFACE_BDR)
-    ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
-  else
-    ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+      if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (oi->state == OSPF6_INTERFACE_DR) ||
+	  (oi->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+      else
+	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+
+    }
 
   if (oi->lsupdate_list->count > 0)
     {
@@ -2140,6 +2178,7 @@
   struct ospf6_header *oh;
   u_char *p;
   struct ospf6_lsa *lsa;
+  int lsa_cnt = 0;
 
   on = (struct ospf6_neighbor *) THREAD_ARG (thread);
   on->thread_send_lsack = (struct thread *) NULL;
@@ -2166,16 +2205,16 @@
     {
       /* MTU check */
       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if))
-        {
-          /* if we run out of packet size/space here,
-             better to try again soon. */
-          THREAD_OFF (on->thread_send_lsack);
-          on->thread_send_lsack =
-            thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
+	{
+	  /* if we run out of packet size/space here,
+	     better to try again soon. */
+	  THREAD_OFF (on->thread_send_lsack);
+	  on->thread_send_lsack =
+	    thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
 
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	  ospf6_lsdb_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, on->ospf6_if->transdelay);
       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@@ -2183,13 +2222,24 @@
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, on->lsack_list);
+      lsa_cnt++;
     }
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSACK;
-  oh->length = htons (p - sendbuf);
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+      oh->length = htons (p - sendbuf);
 
-  ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
-              on->ospf6_if, oh);
+      ospf6_send (on->ospf6_if->linklocal_addr, &on->linklocal_addr,
+		  on->ospf6_if, oh);
+    }
+
+  if (on->thread_send_lsack == NULL && on->lsack_list->count > 0)
+    {
+      on->thread_send_lsack =
+        thread_add_event (master, ospf6_lsack_send_neighbor, on, 0);
+    }
+
   return 0;
 }
 
@@ -2200,6 +2250,7 @@
   struct ospf6_header *oh;
   u_char *p;
   struct ospf6_lsa *lsa;
+  int lsa_cnt = 0;
 
   oi = (struct ospf6_interface *) THREAD_ARG (thread);
   oi->thread_send_lsack = (struct thread *) NULL;
@@ -2226,16 +2277,16 @@
     {
       /* MTU check */
       if (p - sendbuf + sizeof (struct ospf6_lsa_header) > ospf6_packet_max(oi))
-        {
-          /* if we run out of packet size/space here,
-             better to try again soon. */
-          THREAD_OFF (oi->thread_send_lsack);
-          oi->thread_send_lsack =
-            thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
+	{
+	  /* if we run out of packet size/space here,
+	     better to try again soon. */
+	  THREAD_OFF (oi->thread_send_lsack);
+	  oi->thread_send_lsack =
+	    thread_add_event (master, ospf6_lsack_send_interface, oi, 0);
 
-          ospf6_lsa_unlock (lsa);
-          break;
-        }
+	  ospf6_lsdb_lsa_unlock (lsa);
+	  break;
+	}
 
       ospf6_lsa_age_update_to_send (lsa, oi->transdelay);
       memcpy (p, lsa->header, sizeof (struct ospf6_lsa_header));
@@ -2243,16 +2294,21 @@
 
       assert (lsa->lock == 2);
       ospf6_lsdb_remove (lsa, oi->lsack_list);
+      lsa_cnt++;
     }
 
-  oh->type = OSPF6_MESSAGE_TYPE_LSACK;
-  oh->length = htons (p - sendbuf);
+  if (lsa_cnt)
+    {
+      oh->type = OSPF6_MESSAGE_TYPE_LSACK;
+      oh->length = htons (p - sendbuf);
 
-  if (oi->state == OSPF6_INTERFACE_DR ||
-      oi->state == OSPF6_INTERFACE_BDR)
-    ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
-  else
-    ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+      if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT) ||
+	  (oi->state == OSPF6_INTERFACE_DR) ||
+	  (oi->state == OSPF6_INTERFACE_BDR))
+	ospf6_send (oi->linklocal_addr, &allspfrouters6, oi, oh);
+      else
+	ospf6_send (oi->linklocal_addr, &alldrouters6, oi, oh);
+    }
 
   if (oi->thread_send_lsack == NULL && oi->lsack_list->count > 0)
     {
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 806767d..fb209fd 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -98,7 +98,6 @@
   on->retrans_list = ospf6_lsdb_create (on);
 
   on->dbdesc_list = ospf6_lsdb_create (on);
-  on->lsreq_list = ospf6_lsdb_create (on);
   on->lsupdate_list = ospf6_lsdb_create (on);
   on->lsack_list = ospf6_lsdb_create (on);
 
@@ -121,7 +120,6 @@
     }
 
   ospf6_lsdb_remove_all (on->dbdesc_list);
-  ospf6_lsdb_remove_all (on->lsreq_list);
   ospf6_lsdb_remove_all (on->lsupdate_list);
   ospf6_lsdb_remove_all (on->lsack_list);
 
@@ -130,7 +128,6 @@
   ospf6_lsdb_delete (on->retrans_list);
 
   ospf6_lsdb_delete (on->dbdesc_list);
-  ospf6_lsdb_delete (on->lsreq_list);
   ospf6_lsdb_delete (on->lsupdate_list);
   ospf6_lsdb_delete (on->lsack_list);
 
@@ -145,7 +142,7 @@
 }
 
 static void
-ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on)
+ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int event)
 {
   u_char prev_state;
 
@@ -161,11 +158,23 @@
   /* log */
   if (IS_OSPF6_DEBUG_NEIGHBOR (STATE))
     {
-      zlog_debug ("Neighbor state change %s: [%s]->[%s]", on->name,
+      zlog_debug ("Neighbor state change %s: [%s]->[%s] (%s)", on->name,
 		  ospf6_neighbor_state_str[prev_state],
-		  ospf6_neighbor_state_str[next_state]);
+		  ospf6_neighbor_state_str[next_state],
+		  ospf6_neighbor_event_string(event));
     }
 
+  /* Optionally notify about adjacency changes */
+  if (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
+		 OSPF6_LOG_ADJACENCY_CHANGES) &&
+      (CHECK_FLAG(on->ospf6_if->area->ospf6->config_flags,
+		  OSPF6_LOG_ADJACENCY_DETAIL) ||
+       (next_state == OSPF6_NEIGHBOR_FULL) || (next_state < prev_state)))
+    zlog_notice("AdjChg: Nbr %s: %s -> %s (%s)", on->name,
+		ospf6_neighbor_state_str[prev_state],
+		ospf6_neighbor_state_str[next_state],
+		ospf6_neighbor_event_string(event));
+
   if (prev_state == OSPF6_NEIGHBOR_FULL || next_state == OSPF6_NEIGHBOR_FULL)
     {
       OSPF6_ROUTER_LSA_SCHEDULE (on->ospf6_if->area);
@@ -226,7 +235,8 @@
                                            on->ospf6_if->dead_interval);
 
   if (on->state <= OSPF6_NEIGHBOR_DOWN)
-    ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
+    ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
+				 OSPF6_NEIGHBOR_EVENT_HELLO_RCVD);
 
   return 0;
 }
@@ -249,11 +259,13 @@
 
   if (! need_adjacency (on))
     {
-      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
+      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
+				   OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
       return 0;
     }
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
+			       OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@@ -330,7 +342,8 @@
     }
 
   UNSET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXCHANGE, on,
+			       OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE);
 
   return 0;
 }
@@ -358,13 +371,45 @@
 */
 
   if (on->request_list->count == 0)
-    ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
+    ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
+				 OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
   else
-    ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on);
+    {
+      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_LOADING, on,
+				   OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE);
+
+      if (on->thread_send_lsreq == NULL)
+	on->thread_send_lsreq =
+	  thread_add_event (master, ospf6_lsreq_send, on, 0);
+    }
 
   return 0;
 }
 
+/* Check loading state. */
+void
+ospf6_check_nbr_loading (struct ospf6_neighbor *on)
+{
+
+  /* RFC2328 Section 10.9: When the neighbor responds to these requests
+     with the proper Link State Update packet(s), the Link state request
+     list is truncated and a new Link State Request packet is sent.
+  */
+  if ((on->state == OSPF6_NEIGHBOR_LOADING) ||
+      (on->state == OSPF6_NEIGHBOR_EXCHANGE))
+    {
+      if (on->request_list->count == 0)
+	thread_add_event (master, loading_done, on, 0);
+      else if (on->last_ls_req == NULL)
+	{
+	  if (on->thread_send_lsreq != NULL)
+	    THREAD_OFF (on->thread_send_lsreq);
+	  on->thread_send_lsreq =
+	    thread_add_event (master, ospf6_lsreq_send, on, 0);
+	}
+    }
+}
+
 int
 loading_done (struct thread *thread)
 {
@@ -381,7 +426,8 @@
 
   assert (on->request_list->count == 0);
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_FULL, on,
+			       OSPF6_NEIGHBOR_EVENT_LOADING_DONE);
 
   return 0;
 }
@@ -400,7 +446,8 @@
 
   if (on->state == OSPF6_NEIGHBOR_TWOWAY && need_adjacency (on))
     {
-      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
+				   OSPF6_NEIGHBOR_EVENT_ADJ_OK);
       SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
       SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
       SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@@ -413,7 +460,8 @@
   else if (on->state >= OSPF6_NEIGHBOR_EXSTART &&
            ! need_adjacency (on))
     {
-      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on);
+      ospf6_neighbor_state_change (OSPF6_NEIGHBOR_TWOWAY, on,
+				   OSPF6_NEIGHBOR_EVENT_ADJ_OK);
       ospf6_lsdb_remove_all (on->summary_list);
       ospf6_lsdb_remove_all (on->request_list);
       for (lsa = ospf6_lsdb_head (on->retrans_list); lsa;
@@ -442,7 +490,8 @@
   if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
     zlog_debug ("Neighbor Event %s: *SeqNumberMismatch*", on->name);
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
+			       OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@@ -457,6 +506,8 @@
     }
 
   THREAD_OFF (on->thread_send_dbdesc);
+  on->dbdesc_seqnum++;		/* Incr seqnum as per RFC2328, sec 10.3 */
+
   on->thread_send_dbdesc =
     thread_add_event (master, ospf6_dbdesc_send, on, 0);
 
@@ -478,7 +529,8 @@
   if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
     zlog_debug ("Neighbor Event %s: *BadLSReq*", on->name);
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_EXSTART, on,
+			       OSPF6_NEIGHBOR_EVENT_BAD_LSREQ);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MSBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_MBIT);
   SET_FLAG (on->dbdesc_bits, OSPF6_DBDESC_IBIT);
@@ -493,6 +545,8 @@
     }
 
   THREAD_OFF (on->thread_send_dbdesc);
+  on->dbdesc_seqnum++;		/* Incr seqnum as per RFC2328, sec 10.3 */
+
   on->thread_send_dbdesc =
     thread_add_event (master, ospf6_dbdesc_send, on, 0);
 
@@ -514,7 +568,8 @@
   if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT))
     zlog_debug ("Neighbor Event %s: *1Way-Received*", on->name);
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_INIT, on,
+			       OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD);
   thread_add_event (master, neighbor_change, on->ospf6_if, 0);
 
   ospf6_lsdb_remove_all (on->summary_list);
@@ -549,7 +604,8 @@
   on->drouter = on->prev_drouter = 0;
   on->bdrouter = on->prev_bdrouter = 0;
 
-  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on);
+  ospf6_neighbor_state_change (OSPF6_NEIGHBOR_DOWN, on,
+			       OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER);
   thread_add_event (master, neighbor_change, on->ospf6_if, 0);
 
   listnode_delete (on->ospf6_if->neighbor_list, on);
@@ -727,10 +783,10 @@
     timersub (&on->thread_send_lsreq->u.sands, &now, &res);
   timerstring (&res, duration, sizeof (duration));
   vty_out (vty, "    %d Pending LSAs for LSReq in Time %s [thread %s]%s",
-           on->lsreq_list->count, duration,
+           on->request_list->count, duration,
            (on->thread_send_lsreq ? "on" : "off"),
            VNL);
-  for (lsa = ospf6_lsdb_head (on->lsreq_list); lsa;
+  for (lsa = ospf6_lsdb_head (on->request_list); lsa;
        lsa = ospf6_lsdb_next (lsa))
     vty_out (vty, "      %s%s", lsa->name, VNL);
 
diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h
index 5f46c6f..8882189 100644
--- a/ospf6d/ospf6_neighbor.h
+++ b/ospf6d/ospf6_neighbor.h
@@ -86,6 +86,8 @@
   struct ospf6_lsdb *lsupdate_list;
   struct ospf6_lsdb *lsack_list;
 
+  struct ospf6_lsa *last_ls_req;
+
   /* Inactivity timer */
   struct thread *inactivity_timer;
 
@@ -106,6 +108,44 @@
 #define OSPF6_NEIGHBOR_LOADING  7
 #define OSPF6_NEIGHBOR_FULL     8
 
+/* Neighbor Events */
+#define OSPF6_NEIGHBOR_EVENT_NO_EVENT             0
+#define OSPF6_NEIGHBOR_EVENT_HELLO_RCVD           1
+#define OSPF6_NEIGHBOR_EVENT_TWOWAY_RCVD          2
+#define OSPF6_NEIGHBOR_EVENT_NEGOTIATION_DONE     3
+#define OSPF6_NEIGHBOR_EVENT_EXCHANGE_DONE        4
+#define OSPF6_NEIGHBOR_EVENT_LOADING_DONE         5
+#define OSPF6_NEIGHBOR_EVENT_ADJ_OK               6
+#define OSPF6_NEIGHBOR_EVENT_SEQNUMBER_MISMATCH   7
+#define OSPF6_NEIGHBOR_EVENT_BAD_LSREQ            8
+#define OSPF6_NEIGHBOR_EVENT_ONEWAY_RCVD          9
+#define OSPF6_NEIGHBOR_EVENT_INACTIVITY_TIMER    10
+#define OSPF6_NEIGHBOR_EVENT_MAX_EVENT           11
+
+static const char *ospf6_neighbor_event_str[] =
+  {
+    "NoEvent",
+    "HelloReceived",
+    "2-WayReceived",
+    "NegotiationDone",
+    "ExchangeDone",
+    "LoadingDone",
+    "AdjOK?",
+    "SeqNumberMismatch",
+    "BadLSReq",
+    "1-WayReceived",
+    "InactivityTimer",
+  };
+
+static const char *ospf6_neighbor_event_string (int event)
+{
+  #define OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING "UnknownEvent"
+
+  if (event < OSPF6_NEIGHBOR_EVENT_MAX_EVENT)
+      return ospf6_neighbor_event_str[event];
+  return OSPF6_NEIGHBOR_UNKNOWN_EVENT_STRING;
+}
+
 extern const char *ospf6_neighbor_state_str[];
 
 
@@ -130,6 +170,7 @@
 extern int bad_lsreq (struct thread *);
 extern int oneway_received (struct thread *);
 extern int inactivity_timer (struct thread *);
+extern void ospf6_check_nbr_loading (struct ospf6_neighbor *);
 
 extern void ospf6_neighbor_init (void);
 extern int config_write_ospf6_debug_neighbor (struct vty *vty);
diff --git a/ospf6d/ospf6_network.c b/ospf6d/ospf6_network.c
index e5a1436..74cfbec 100644
--- a/ospf6d/ospf6_network.c
+++ b/ospf6d/ospf6_network.c
@@ -27,6 +27,7 @@
 #include "sockopt.h"
 #include "privs.h"
 
+#include "libospf.h"
 #include "ospf6_proto.h"
 #include "ospf6_network.h"
 
@@ -205,7 +206,7 @@
   smsghdr.msg_name = (caddr_t) &dst_sin6;
   smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
   smsghdr.msg_control = (caddr_t) cmsgbuf;
-  smsghdr.msg_controllen = sizeof (cmsgbuf);
+  smsghdr.msg_controllen = scmsgp->cmsg_len;
 
   retval = sendmsg (ospf6_sock, &smsghdr, 0);
   if (retval != iov_totallen (message))
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index 6462500..af60eb9 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -26,33 +26,12 @@
 /* OSPF protocol version */
 #define OSPFV3_VERSION           3
 
-/* OSPF protocol number. */
-#ifndef IPPROTO_OSPFIGP
-#define IPPROTO_OSPFIGP         89
-#endif
-
 /* TOS field normaly null */
 #define DEFAULT_TOS_VALUE      0x0
 
-/* Architectural Constants */
-#define LS_REFRESH_TIME                1800  /* 30 min */
-#define MIN_LS_INTERVAL                   5
-#define MIN_LS_ARRIVAL                    1
-#define MAXAGE                         3600  /* 1 hour */
-#define CHECK_AGE                       300  /* 5 min */
-#define MAX_AGE_DIFF                    900  /* 15 min */
-#define LS_INFINITY                0xffffff  /* 24-bit binary value */
-#define INITIAL_SEQUENCE_NUMBER  0x80000001  /* signed 32-bit integer */
-#define MAX_SEQUENCE_NUMBER      0x7fffffff  /* signed 32-bit integer */
-
 #define ALLSPFROUTERS6 "ff02::5"
 #define ALLDROUTERS6   "ff02::6"
 
-/* Configurable Constants */
-
-#define DEFAULT_HELLO_INTERVAL       10
-#define DEFAULT_ROUTER_DEAD_INTERVAL 40
-
 #define OSPF6_ROUTER_BIT_W     (1 << 3)
 #define OSPF6_ROUTER_BIT_V     (1 << 2)
 #define OSPF6_ROUTER_BIT_E     (1 << 1)
diff --git a/ospf6d/ospf6_route.c b/ospf6d/ospf6_route.c
index 398acfa..5f1869a 100644
--- a/ospf6d/ospf6_route.c
+++ b/ospf6d/ospf6_route.c
@@ -304,7 +304,7 @@
   return route;
 }
 
-#ifndef NDEBUG
+#ifdef DEBUG
 static void
 route_table_assert (struct ospf6_route_table *table)
 {
@@ -350,7 +350,7 @@
 #define ospf6_route_table_assert(t) (route_table_assert (t))
 #else
 #define ospf6_route_table_assert(t) ((void) 0)
-#endif /*NDEBUG*/
+#endif /*DEBUG*/
 
 struct ospf6_route *
 ospf6_route_add (struct ospf6_route *route,
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index da0ee13..3ef5485 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -377,6 +377,36 @@
     }
 }
 
+static const char *ospf6_spf_reason_str[] =
+  {
+    "R+",
+    "R-",
+    "N+",
+    "N-",
+    "L+",
+    "L-",
+    "R*",
+    "N*",
+  };
+
+void ospf6_spf_reason_string (unsigned int reason, char *buf, int size)
+{
+  int bit;
+  int len = 0;
+
+  if (!buf)
+    return;
+
+  for (bit = 0; bit <= (sizeof(ospf6_spf_reason_str) / sizeof(char *)); bit++)
+    {
+      if ((reason & (1 << bit)) && (len < size))
+	{
+	  len += snprintf((buf + len), (size - len), "%s%s",
+			  (len > 0) ? ", " : "", ospf6_spf_reason_str[bit]);
+	}
+    }
+}
+
 /* RFC2328 16.1.  Calculating the shortest-path tree for an area */
 /* RFC2740 3.8.1.  Calculating the shortest path tree for an area */
 void
@@ -424,6 +454,11 @@
       if (ospf6_spf_install (v, result_table) < 0)
         continue;
 
+      /* Skip overloaded routers */
+      if ((OSPF6_LSA_IS_TYPE (ROUTER, v->lsa) &&
+	   ospf6_router_is_stub_router (v->lsa)))
+	continue;
+
       /* For each LS description in the just-added vertex V's LSA */
       size = (VERTEX_IS_TYPE (ROUTER, v) ?
               sizeof (struct ospf6_router_lsdesc) :
@@ -506,39 +541,146 @@
 ospf6_spf_calculation_thread (struct thread *t)
 {
   struct ospf6_area *oa;
+  struct ospf6 *ospf6;
   struct timeval start, end, runtime;
+  struct listnode *node;
+  struct ospf6_route *route;
+  int areas_processed = 0;
+  char rbuf[32];
 
-  oa = (struct ospf6_area *) THREAD_ARG (t);
-  oa->thread_spf_calculation = NULL;
-
-  if (IS_OSPF6_DEBUG_SPF (PROCESS))
-    zlog_debug ("SPF calculation for Area %s", oa->name);
-  if (IS_OSPF6_DEBUG_SPF (DATABASE))
-    ospf6_spf_log_database (oa);
+  ospf6 = (struct ospf6 *)THREAD_ARG (t);
+  ospf6->t_spf_calc = NULL;
 
   /* execute SPF calculation */
   quagga_gettime (QUAGGA_CLK_MONOTONIC, &start);
-  ospf6_spf_calculation (oa->ospf6->router_id, oa->spf_table, oa);
+
+  for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa))
+    {
+
+      if (oa == ospf6->backbone)
+	continue;
+
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
+	zlog_debug ("SPF calculation for Area %s", oa->name);
+      if (IS_OSPF6_DEBUG_SPF (DATABASE))
+	ospf6_spf_log_database (oa);
+
+      ospf6_spf_calculation (ospf6->router_id, oa->spf_table, oa);
+      ospf6_intra_route_calculation (oa);
+      ospf6_intra_brouter_calculation (oa);
+
+      areas_processed++;
+    }
+
+  if (ospf6->backbone)
+    {
+      if (IS_OSPF6_DEBUG_SPF (PROCESS))
+	zlog_debug ("SPF calculation for Backbone area %s",
+		    ospf6->backbone->name);
+      if (IS_OSPF6_DEBUG_SPF (DATABASE))
+	ospf6_spf_log_database(ospf6->backbone);
+
+      ospf6_spf_calculation(ospf6->router_id, ospf6->backbone->spf_table,
+			    ospf6->backbone);
+      ospf6_intra_route_calculation(ospf6->backbone);
+      ospf6_intra_brouter_calculation(ospf6->backbone);
+      areas_processed++;
+    }
+
+  /* Redo summaries if required */
+  for (route = ospf6_route_head (ospf6->route_table); route;
+       route = ospf6_route_next (route))
+    ospf6_abr_originate_summary(route);
+
   quagga_gettime (QUAGGA_CLK_MONOTONIC, &end);
   timersub (&end, &start, &runtime);
 
+  ospf6->ts_spf_duration = runtime;
+
+  ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
+
   if (IS_OSPF6_DEBUG_SPF (PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
     zlog_debug ("SPF runtime: %ld sec %ld usec",
 		runtime.tv_sec, runtime.tv_usec);
 
-  ospf6_intra_route_calculation (oa);
-  ospf6_intra_brouter_calculation (oa);
-
+  zlog_info("SPF processing: # Areas: %d, SPF runtime: %ld sec %ld usec, "
+	    "Reason: %s\n", areas_processed, runtime.tv_sec, runtime.tv_usec,
+	    rbuf);
+  ospf6->last_spf_reason = ospf6->spf_reason;
+  ospf6_reset_spf_reason(ospf6);
   return 0;
 }
 
+/* Add schedule for SPF calculation.  To avoid frequenst SPF calc, we
+   set timer for SPF calc. */
 void
-ospf6_spf_schedule (struct ospf6_area *oa)
+ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason)
 {
-  if (oa->thread_spf_calculation)
+  unsigned long delay, elapsed, ht;
+  struct timeval now, result;
+
+  ospf6_set_spf_reason(ospf6, reason);
+
+  if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
+    {
+      char rbuf[32];
+      ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
+      zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf);
+    }
+
+  /* OSPF instance does not exist. */
+  if (ospf6 == NULL)
     return;
-  oa->thread_spf_calculation =
-    thread_add_event (master, ospf6_spf_calculation_thread, oa, 0);
+
+  /* SPF calculation timer is already scheduled. */
+  if (ospf6->t_spf_calc)
+    {
+      if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
+        zlog_debug ("SPF: calculation timer is already scheduled: %p",
+                   ospf6->t_spf_calc);
+      return;
+    }
+
+  /* XXX Monotic timers: we only care about relative time here. */
+  now = recent_relative_time ();
+  timersub (&now, &ospf6->ts_spf, &result);
+
+  elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
+  ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;
+
+  if (ht > ospf6->spf_max_holdtime)
+    ht = ospf6->spf_max_holdtime;
+
+  /* Get SPF calculation delay time. */
+  if (elapsed < ht)
+    {
+      /* Got an event within the hold time of last SPF. We need to
+       * increase the hold_multiplier, if it's not already at/past
+       * maximum value, and wasn't already increased..
+       */
+      if (ht < ospf6->spf_max_holdtime)
+        ospf6->spf_hold_multiplier++;
+
+      /* always honour the SPF initial delay */
+      if ( (ht - elapsed) < ospf6->spf_delay)
+        delay = ospf6->spf_delay;
+      else
+        delay = ht - elapsed;
+    }
+  else
+    {
+      /* Event is past required hold-time of last SPF */
+      delay = ospf6->spf_delay;
+      ospf6->spf_hold_multiplier = 1;
+    }
+
+  if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
+    zlog_debug ("SPF: calculation timer delay = %ld", delay);
+
+  zlog_info ("SPF: Scheduled in %ld msec", delay);
+
+  ospf6->t_spf_calc =
+    thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay);
 }
 
 void
@@ -666,6 +808,59 @@
   return CMD_SUCCESS;
 }
 
+static int
+ospf6_timers_spf_set (struct vty *vty, unsigned int delay,
+                     unsigned int hold,
+                     unsigned int max)
+{
+  struct ospf6 *ospf = vty->index;
+
+  ospf->spf_delay = delay;
+  ospf->spf_holdtime = hold;
+  ospf->spf_max_holdtime = max;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_timers_throttle_spf,
+       ospf6_timers_throttle_spf_cmd,
+       "timers throttle spf <0-600000> <0-600000> <0-600000>",
+       "Adjust routing timers\n"
+       "Throttling adaptive timer\n"
+       "OSPF6 SPF timers\n"
+       "Delay (msec) from first change received till SPF calculation\n"
+       "Initial hold time (msec) between consecutive SPF calculations\n"
+       "Maximum hold time (msec)\n")
+{
+  unsigned int delay, hold, max;
+
+  if (argc != 3)
+    {
+      vty_out (vty, "Insufficient arguments%s", VTY_NEWLINE);
+      return CMD_WARNING;
+    }
+
+  VTY_GET_INTEGER_RANGE ("SPF delay timer", delay, argv[0], 0, 600000);
+  VTY_GET_INTEGER_RANGE ("SPF hold timer", hold, argv[1], 0, 600000);
+  VTY_GET_INTEGER_RANGE ("SPF max-hold timer", max, argv[2], 0, 600000);
+
+  return ospf6_timers_spf_set (vty, delay, hold, max);
+}
+
+DEFUN (no_ospf6_timers_throttle_spf,
+       no_ospf6_timers_throttle_spf_cmd,
+       "no timers throttle spf",
+       NO_STR
+       "Adjust routing timers\n"
+       "Throttling adaptive timer\n"
+       "OSPF6 SPF timers\n")
+{
+  return ospf6_timers_spf_set (vty,
+                              OSPF_SPF_DELAY_DEFAULT,
+                              OSPF_SPF_HOLDTIME_DEFAULT,
+                              OSPF_SPF_MAX_HOLDTIME_DEFAULT);
+}
+
 int
 config_write_ospf6_debug_spf (struct vty *vty)
 {
@@ -679,6 +874,19 @@
 }
 
 void
+ospf6_spf_config_write (struct vty *vty)
+{
+
+  if (ospf6->spf_delay != OSPF_SPF_DELAY_DEFAULT ||
+      ospf6->spf_holdtime != OSPF_SPF_HOLDTIME_DEFAULT ||
+      ospf6->spf_max_holdtime != OSPF_SPF_MAX_HOLDTIME_DEFAULT)
+    vty_out (vty, " timers throttle spf %d %d %d%s",
+	     ospf6->spf_delay, ospf6->spf_holdtime,
+	     ospf6->spf_max_holdtime, VTY_NEWLINE);
+
+}
+
+void
 install_element_ospf6_debug_spf (void)
 {
   install_element (ENABLE_NODE, &debug_ospf6_spf_process_cmd);
@@ -698,6 +906,6 @@
 void
 ospf6_spf_init (void)
 {
+  install_element (OSPF6_NODE, &ospf6_timers_throttle_spf_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_timers_throttle_spf_cmd);
 }
-
-
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index c7069c2..b3481dc 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -22,6 +22,8 @@
 #ifndef OSPF6_SPF_H
 #define OSPF6_SPF_H
 
+#include "ospf6_top.h"
+
 /* Debug option */
 extern unsigned char conf_debug_ospf6_spf;
 #define OSPF6_DEBUG_SPF_PROCESS   0x01
@@ -77,18 +79,86 @@
 #define VERTEX_IS_TYPE(t, v) \
   ((v)->type == OSPF6_VERTEX_TYPE_ ## t ? 1 : 0)
 
+/* What triggered the SPF? */
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED         (1 << 0)
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED       (1 << 1)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED        (1 << 2)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED      (1 << 3)
+#define OSPF6_SPF_FLAGS_LINK_LSA_ADDED           (1 << 4)
+#define OSPF6_SPF_FLAGS_LINK_LSA_REMOVED         (1 << 5)
+#define OSPF6_SPF_FLAGS_ROUTER_LSA_ORIGINATED    (1 << 6)
+#define OSPF6_SPF_FLAGS_NETWORK_LSA_ORIGINATED   (1 << 7)
+
+static inline void
+ospf6_set_spf_reason (struct ospf6* ospf, unsigned int reason)
+{
+  ospf->spf_reason |= reason;
+}
+
+static inline void
+ospf6_reset_spf_reason (struct ospf6 *ospf)
+{
+  ospf->spf_reason = 0;
+}
+
+static inline unsigned int
+ospf6_lsadd_to_spf_reason (struct ospf6_lsa *lsa)
+{
+  unsigned int reason = 0;
+
+  switch (ntohs (lsa->header->type))
+    {
+    case OSPF6_LSTYPE_ROUTER:
+      reason = OSPF6_SPF_FLAGS_ROUTER_LSA_ADDED;
+      break;
+    case OSPF6_LSTYPE_NETWORK:
+      reason = OSPF6_SPF_FLAGS_NETWORK_LSA_ADDED;
+      break;
+    case OSPF6_LSTYPE_LINK:
+      reason = OSPF6_SPF_FLAGS_LINK_LSA_ADDED;
+      break;
+    default:
+      break;
+    }
+  return (reason);
+}
+
+static inline unsigned int
+ospf6_lsremove_to_spf_reason (struct ospf6_lsa *lsa)
+{
+  unsigned int reason = 0;
+
+  switch (ntohs (lsa->header->type))
+    {
+    case OSPF6_LSTYPE_ROUTER:
+      reason = OSPF6_SPF_FLAGS_ROUTER_LSA_REMOVED;
+      break;
+    case OSPF6_LSTYPE_NETWORK:
+      reason = OSPF6_SPF_FLAGS_NETWORK_LSA_REMOVED;
+      break;
+    case OSPF6_LSTYPE_LINK:
+      reason = OSPF6_SPF_FLAGS_LINK_LSA_REMOVED;
+      break;
+    default:
+      break;
+    }
+  return (reason);
+}
+
 extern void ospf6_spf_table_finish (struct ospf6_route_table *result_table);
 extern void ospf6_spf_calculation (u_int32_t router_id,
                                    struct ospf6_route_table *result_table,
                                    struct ospf6_area *oa);
-extern void ospf6_spf_schedule (struct ospf6_area *oa);
+extern void ospf6_spf_schedule (struct ospf6 *ospf, unsigned int reason);
 
 extern void ospf6_spf_display_subtree (struct vty *vty, const char *prefix,
                                        int rest, struct ospf6_vertex *v);
 
+extern void ospf6_spf_config_write (struct vty *vty);
 extern int config_write_ospf6_debug_spf (struct vty *vty);
 extern void install_element_ospf6_debug_spf (void);
 extern void ospf6_spf_init (void);
+extern void ospf6_spf_reason_string (unsigned int reason, char *buf, int size);
 
 #endif /* OSPF6_SPF_H */
 
diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c
index df856b4..7c0922a 100644
--- a/ospf6d/ospf6_top.c
+++ b/ospf6d/ospf6_top.c
@@ -46,6 +46,7 @@
 #include "ospf6_asbr.h"
 #include "ospf6_abr.h"
 #include "ospf6_intra.h"
+#include "ospf6_spf.h"
 #include "ospf6d.h"
 
 /* global ospf6d variable */
@@ -127,6 +128,11 @@
   o->lsdb->hook_add = ospf6_top_lsdb_hook_add;
   o->lsdb->hook_remove = ospf6_top_lsdb_hook_remove;
 
+  o->spf_delay = OSPF_SPF_DELAY_DEFAULT;
+  o->spf_holdtime = OSPF_SPF_HOLDTIME_DEFAULT;
+  o->spf_max_holdtime = OSPF_SPF_MAX_HOLDTIME_DEFAULT;
+  o->spf_hold_multiplier = 1;
+
   o->route_table = OSPF6_ROUTE_TABLE_CREATE (GLOBAL, ROUTES);
   o->route_table->scope = o;
   o->route_table->hook_add = ospf6_top_route_hook_add;
@@ -155,6 +161,8 @@
 
   for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
     ospf6_area_delete (oa);
+
+
   list_delete (o->area_list);
 
   ospf6_lsdb_delete (o->lsdb);
@@ -196,13 +204,20 @@
       for (ALL_LIST_ELEMENTS (o->area_list, node, nnode, oa))
         ospf6_area_disable (oa);
 
+      /* XXX: This also changes persistent settings */
+      ospf6_asbr_redistribute_reset();
+
       ospf6_lsdb_remove_all (o->lsdb);
       ospf6_route_remove_all (o->route_table);
       ospf6_route_remove_all (o->brouter_table);
+
+      THREAD_OFF(o->maxage_remover);
+      THREAD_OFF(o->t_spf_calc);
+      THREAD_OFF(o->t_ase_calc);
     }
 }
 
-static int
+int
 ospf6_maxage_remover (struct thread *thread)
 {
   struct ospf6 *o = (struct ospf6 *) THREAD_ARG (thread);
@@ -210,6 +225,7 @@
   struct ospf6_interface *oi;
   struct ospf6_neighbor *on;
   struct listnode *i, *j, *k;
+  int reschedule = 0;
 
   o->maxage_remover = (struct thread *) NULL;
 
@@ -221,8 +237,9 @@
             {
               if (on->state != OSPF6_NEIGHBOR_EXCHANGE &&
                   on->state != OSPF6_NEIGHBOR_LOADING)
-                continue;
+		  continue;
 
+	      ospf6_maxage_remove (o);
               return 0;
             }
         }
@@ -231,11 +248,28 @@
   for (ALL_LIST_ELEMENTS_RO (o->area_list, i, oa))
     {
       for (ALL_LIST_ELEMENTS_RO (oa->if_list, j, oi))
-        OSPF6_LSDB_MAXAGE_REMOVER (oi->lsdb);
+	{
+	  if (ospf6_lsdb_maxage_remover (oi->lsdb))
+	    {
+	      reschedule = 1;
+	    }
+	}
       
-      OSPF6_LSDB_MAXAGE_REMOVER (oa->lsdb);
+      if (ospf6_lsdb_maxage_remover (oa->lsdb))
+	{
+	    reschedule = 1;
+	}
     }
-  OSPF6_LSDB_MAXAGE_REMOVER (o->lsdb);
+
+  if (ospf6_lsdb_maxage_remover (o->lsdb))
+    {
+      reschedule = 1;
+    }
+
+  if (reschedule)
+    {
+      ospf6_maxage_remove (o);
+    }
 
   return 0;
 }
@@ -244,7 +278,8 @@
 ospf6_maxage_remove (struct ospf6 *o)
 {
   if (o && ! o->maxage_remover)
-    o->maxage_remover = thread_add_event (master, ospf6_maxage_remover, o, 0);
+    o->maxage_remover = thread_add_timer (master, ospf6_maxage_remover, o,
+					  OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT);
 }
 
 /* start ospf6 */
@@ -256,8 +291,6 @@
 {
   if (ospf6 == NULL)
     ospf6 = ospf6_create ();
-  if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
-    ospf6_enable (ospf6);
 
   /* set current ospf point. */
   vty->node = OSPF6_NODE;
@@ -273,10 +306,13 @@
        NO_STR
        OSPF6_ROUTER_STR)
 {
-  if (ospf6 == NULL || CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
-    vty_out (vty, "OSPFv3 is not running%s", VNL);
+  if (ospf6 == NULL)
+    vty_out (vty, "OSPFv3 is not configured%s", VNL);
   else
-    ospf6_disable (ospf6);
+    {
+      ospf6_delete (ospf6);
+      ospf6 = NULL;
+    }
 
   /* return to config node . */
   vty->node = CONFIG_NODE;
@@ -312,6 +348,56 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (ospf6_log_adjacency_changes,
+       ospf6_log_adjacency_changes_cmd,
+       "log-adjacency-changes",
+       "Log changes in adjacency state\n")
+{
+  struct ospf6 *ospf6 = vty->index;
+
+  SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_log_adjacency_changes_detail,
+       ospf6_log_adjacency_changes_detail_cmd,
+       "log-adjacency-changes detail",
+              "Log changes in adjacency state\n"
+       "Log all state changes\n")
+{
+  struct ospf6 *ospf6 = vty->index;
+
+  SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
+  SET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_log_adjacency_changes,
+       no_ospf6_log_adjacency_changes_cmd,
+       "no log-adjacency-changes",
+              NO_STR
+       "Log changes in adjacency state\n")
+{
+  struct ospf6 *ospf6 = vty->index;
+
+  UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
+  UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES);
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_log_adjacency_changes_detail,
+       no_ospf6_log_adjacency_changes_detail_cmd,
+       "no log-adjacency-changes detail",
+              NO_STR
+              "Log changes in adjacency state\n"
+       "Log all state changes\n")
+{
+  struct ospf6 *ospf6 = vty->index;
+
+  UNSET_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL);
+  return CMD_SUCCESS;
+}
+
 DEFUN (ospf6_interface_area,
        ospf6_interface_area_cmd,
        "interface IFNAME area A.B.C.D",
@@ -359,8 +445,12 @@
 
   SET_FLAG (oa->flag, OSPF6_AREA_ENABLE);
 
+  /* ospf6 process is currently disabled, not much more to do */
+  if (CHECK_FLAG (o->flag, OSPF6_DISABLED))
+    return CMD_SUCCESS;
+
   /* start up */
-  thread_add_event (master, interface_up, oi, 0);
+  ospf6_interface_enable (oi);
 
   /* If the router is ABR, originate summary routes */
   if (ospf6_is_router_abr (o))
@@ -438,13 +528,109 @@
   return CMD_SUCCESS;
 }
 
+DEFUN (ospf6_stub_router_admin,
+       ospf6_stub_router_admin_cmd,
+       "stub-router administrative",
+       "Make router a stub router\n"
+       "Advertise inability to be a transit router\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct listnode *node;
+  struct ospf6_area *oa;
+
+  if (!CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+    {
+      for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
+	{
+	   OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_V6);
+	   OSPF6_OPT_CLEAR (oa->options, OSPF6_OPT_R);
+	   OSPF6_ROUTER_LSA_SCHEDULE (oa);
+	}
+      SET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_admin,
+       no_ospf6_stub_router_admin_cmd,
+       "no stub-router administrative",
+       NO_STR
+       "Make router a stub router\n"
+       "Advertise ability to be a transit router\n"
+       "Administratively applied, for an indefinite period\n")
+{
+  struct listnode *node;
+  struct ospf6_area *oa;
+
+  if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+    {
+      for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, node, oa))
+	{
+	   OSPF6_OPT_SET (oa->options, OSPF6_OPT_V6);
+	   OSPF6_OPT_SET (oa->options, OSPF6_OPT_R);
+	   OSPF6_ROUTER_LSA_SCHEDULE (oa);
+	}
+      UNSET_FLAG (ospf6->flag, OSPF6_STUB_ROUTER);
+    }
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_stub_router_startup,
+       ospf6_stub_router_startup_cmd,
+       "stub-router on-startup <5-86400>",
+       "Make router a stub router\n"
+       "Advertise inability to be a transit router\n"
+       "Automatically advertise as stub-router on startup of OSPF6\n"
+       "Time (seconds) to advertise self as stub-router\n")
+{
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_startup,
+       no_ospf6_stub_router_startup_cmd,
+       "no stub-router on-startup",
+       NO_STR
+       "Make router a stub router\n"
+       "Advertise inability to be a transit router\n"
+       "Automatically advertise as stub-router on startup of OSPF6\n"
+       "Time (seconds) to advertise self as stub-router\n")
+{
+  return CMD_SUCCESS;
+}
+
+DEFUN (ospf6_stub_router_shutdown,
+       ospf6_stub_router_shutdown_cmd,
+       "stub-router on-shutdown <5-86400>",
+       "Make router a stub router\n"
+       "Advertise inability to be a transit router\n"
+       "Automatically advertise as stub-router before shutdown\n"
+       "Time (seconds) to advertise self as stub-router\n")
+{
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_ospf6_stub_router_shutdown,
+       no_ospf6_stub_router_shutdown_cmd,
+       "no stub-router on-shutdown",
+       NO_STR
+       "Make router a stub router\n"
+       "Advertise inability to be a transit router\n"
+       "Automatically advertise as stub-router before shutdown\n"
+       "Time (seconds) to advertise self as stub-router\n")
+{
+  return CMD_SUCCESS;
+}
+
 static void
 ospf6_show (struct vty *vty, struct ospf6 *o)
 {
   struct listnode *n;
   struct ospf6_area *oa;
   char router_id[16], duration[32];
-  struct timeval now, running;
+  struct timeval now, running, result;
+  char buf[32], rbuf[32];
 
   /* process id, router id */
   inet_ntop (AF_INET, &o->router_id, router_id, sizeof (router_id));
@@ -460,6 +646,35 @@
   /* Redistribute configuration */
   /* XXX */
 
+  /* Show SPF parameters */
+  vty_out(vty, " Initial SPF scheduling delay %d millisec(s)%s"
+	  " Minimum hold time between consecutive SPFs %d millsecond(s)%s"
+	  " Maximum hold time between consecutive SPFs %d millsecond(s)%s"
+	  " Hold time multiplier is currently %d%s",
+	  o->spf_delay, VNL,
+	  o->spf_holdtime, VNL,
+	  o->spf_max_holdtime, VNL,
+	  o->spf_hold_multiplier, VNL);
+
+  vty_out(vty, " SPF algorithm ");
+  if (o->ts_spf.tv_sec || o->ts_spf.tv_usec)
+    {
+      timersub(&now, &o->ts_spf, &result);
+      timerstring(&result, buf, sizeof(buf));
+      ospf6_spf_reason_string(o->last_spf_reason, rbuf, sizeof(rbuf));
+      vty_out(vty, "last executed %s ago, reason %s%s", buf, rbuf, VNL);
+      vty_out (vty, " Last SPF duration %ld sec %ld usec%s",
+	       o->ts_spf_duration.tv_sec, o->ts_spf_duration.tv_usec, VNL);
+    }
+  else
+    vty_out(vty, "has not been run$%s", VNL);
+  threadtimer_string(now, o->t_spf_calc, buf, sizeof(buf));
+  vty_out (vty, " SPF timer %s%s%s",
+	   (o->t_spf_calc ? "due in " : "is "), buf, VNL);
+
+  if (CHECK_FLAG (o->flag, OSPF6_STUB_ROUTER))
+    vty_out (vty, " Router Is Stub Router%s", VNL);
+
   /* LSAs */
   vty_out (vty, " Number of AS scoped LSAs is %u%s",
            o->lsdb->count, VNL);
@@ -468,6 +683,16 @@
   vty_out (vty, " Number of areas in this router is %u%s",
            listcount (o->area_list), VNL);
 
+  if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
+    {
+      if (CHECK_FLAG(o->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
+	vty_out(vty, " All adjacency changes are logged%s",VTY_NEWLINE);
+      else
+	vty_out(vty, " Adjacency changes are logged%s",VTY_NEWLINE);
+    }
+
+  vty_out (vty, "%s",VTY_NEWLINE);
+
   for (ALL_LIST_ELEMENTS_RO (o->area_list, n, oa))
     ospf6_area_show (vty, oa);
 }
@@ -628,6 +853,16 @@
   return CMD_SUCCESS;
 }
 
+static void
+ospf6_stub_router_config_write (struct vty *vty)
+{
+  if (CHECK_FLAG (ospf6->flag, OSPF6_STUB_ROUTER))
+    {
+      vty_out (vty, " stub-router administrative%s", VNL);
+    }
+    return;
+}
+
 /* OSPF configuration write function. */
 static int
 config_write_ospf6 (struct vty *vty)
@@ -640,16 +875,25 @@
   /* OSPFv6 configuration. */
   if (ospf6 == NULL)
     return CMD_SUCCESS;
-  if (CHECK_FLAG (ospf6->flag, OSPF6_DISABLED))
-    return CMD_SUCCESS;
 
   inet_ntop (AF_INET, &ospf6->router_id_static, router_id, sizeof (router_id));
   vty_out (vty, "router ospf6%s", VNL);
   if (ospf6->router_id_static != 0)
     vty_out (vty, " router-id %s%s", router_id, VNL);
 
+  /* log-adjacency-changes flag print. */
+  if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_CHANGES))
+    {
+      vty_out(vty, " log-adjacency-changes");
+      if (CHECK_FLAG(ospf6->config_flags, OSPF6_LOG_ADJACENCY_DETAIL))
+	vty_out(vty, " detail");
+      vty_out(vty, "%s", VTY_NEWLINE);
+    }
+
+  ospf6_stub_router_config_write (vty);
   ospf6_redistribute_config_write (vty);
   ospf6_area_config_write (vty);
+  ospf6_spf_config_write (vty);
 
   for (ALL_LIST_ELEMENTS_RO (ospf6->area_list, j, oa))
     {
@@ -700,8 +944,20 @@
 
   install_default (OSPF6_NODE);
   install_element (OSPF6_NODE, &ospf6_router_id_cmd);
+  install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_cmd);
+  install_element (OSPF6_NODE, &ospf6_log_adjacency_changes_detail_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_log_adjacency_changes_detail_cmd);
   install_element (OSPF6_NODE, &ospf6_interface_area_cmd);
   install_element (OSPF6_NODE, &no_ospf6_interface_area_cmd);
+  install_element (OSPF6_NODE, &ospf6_stub_router_admin_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_stub_router_admin_cmd);
+  /* For a later time
+  install_element (OSPF6_NODE, &ospf6_stub_router_startup_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_stub_router_startup_cmd);
+  install_element (OSPF6_NODE, &ospf6_stub_router_shutdown_cmd);
+  install_element (OSPF6_NODE, &no_ospf6_stub_router_shutdown_cmd);
+  */
 }
 
 
diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h
index 4b2d2c3..866f92f 100644
--- a/ospf6d/ospf6_top.h
+++ b/ospf6d/ospf6_top.h
@@ -38,6 +38,7 @@
 
   /* list of areas */
   struct list *area_list;
+  struct ospf6_area *backbone;
 
   /* AS scope link state database */
   struct ospf6_lsdb *lsdb;
@@ -59,10 +60,30 @@
 
   u_char flag;
 
+  /* Configured flags */
+  u_char config_flags;
+#define OSPF6_LOG_ADJACENCY_CHANGES      (1 << 0)
+#define OSPF6_LOG_ADJACENCY_DETAIL       (1 << 1)
+
+  /* SPF parameters */
+  unsigned int spf_delay;		/* SPF delay time. */
+  unsigned int spf_holdtime;		/* SPF hold time. */
+  unsigned int spf_max_holdtime;	/* SPF maximum-holdtime */
+  unsigned int spf_hold_multiplier;	/* Adaptive multiplier for hold time */
+  unsigned int spf_reason;              /* reason bits while scheduling SPF */
+
+  struct timeval ts_spf;		/* SPF calculation time stamp. */
+  struct timeval ts_spf_duration;	/* Execution time of last SPF */
+  unsigned int last_spf_reason;         /* Last SPF reason */
+
+  /* Threads */
+  struct thread *t_spf_calc;	        /* SPF calculation timer. */
+  struct thread *t_ase_calc;		/* ASE calculation timer. */
   struct thread *maxage_remover;
 };
 
 #define OSPF6_DISABLED    0x01
+#define OSPF6_STUB_ROUTER 0x02
 
 /* global pointer for OSPF top data structure */
 extern struct ospf6 *ospf6;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index f09e9d2..cffd767 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -117,7 +117,9 @@
 		ifp->name, ifp->ifindex, ifp->mtu6);
 
 #if 0
-  /* Why is this commented out? */
+  /* XXX: ospf6_interface_if_del is not the right way to handle this,
+   * because among other thinkable issues, it will also clear all
+   * settings as they are contained in the struct ospf6_interface. */
   ospf6_interface_if_del (ifp);
 #endif /*0*/
 
@@ -163,8 +165,10 @@
 			   buf, sizeof (buf)), c->address->prefixlen);
 
   if (c->address->family == AF_INET6)
-    ospf6_interface_connected_route_update (c->ifp);
-
+    {
+      ospf6_interface_state_update (c->ifp);
+      ospf6_interface_connected_route_update (c->ifp);
+    }
   return 0;
 }
 
@@ -186,7 +190,10 @@
 			   buf, sizeof (buf)), c->address->prefixlen);
 
   if (c->address->family == AF_INET6)
-    ospf6_interface_connected_route_update (c->ifp);
+    {
+      ospf6_interface_connected_route_update (c->ifp);
+      ospf6_interface_state_update (c->ifp);
+    }
 
   return 0;
 }
diff --git a/ospf6d/ospf6d.h b/ospf6d/ospf6d.h
index 2ac6300..0c86386 100644
--- a/ospf6d/ospf6d.h
+++ b/ospf6d/ospf6d.h
@@ -24,6 +24,9 @@
 
 #define OSPF6_DAEMON_VERSION    "0.9.7r"
 
+#include "libospf.h"
+#include "thread.h"
+
 /* global variables */
 extern struct thread_master *master;
 
@@ -98,6 +101,17 @@
       zlog_warn ("strftime error");                       \
   } while (0)
 
+#define threadtimer_string(now, t, buf, size)                         \
+  do {                                                                \
+    struct timeval result;                                            \
+    if (!t)                                                           \
+      snprintf(buf, size, "inactive");				      \
+    else {                                                            \
+      timersub(&t->u.sands, &now, &result);                           \
+      timerstring(&result, buf, size);                                \
+    }                                                                 \
+} while (0)
+
 /* for commands */
 #define OSPF6_AREA_STR      "Area information\n"
 #define OSPF6_AREA_ID_STR   "Area ID (as an IPv4 notation)\n"
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 9de6550..ed698c8 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -140,14 +140,6 @@
 
   /* OSPF Network Type. */
   u_char type;
-#define OSPF_IFTYPE_NONE		0
-#define OSPF_IFTYPE_POINTOPOINT		1
-#define OSPF_IFTYPE_BROADCAST		2
-#define OSPF_IFTYPE_NBMA		3
-#define OSPF_IFTYPE_POINTOMULTIPOINT	4
-#define OSPF_IFTYPE_VIRTUALLINK		5
-#define OSPF_IFTYPE_LOOPBACK            6
-#define OSPF_IFTYPE_MAX			7
 
   /* State of Interface State Machine. */
   u_char state;
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 3e2b234..538bc09 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -200,7 +200,7 @@
   new->spf_hold_multiplier = 1;
 
   /* MaxAge init. */
-  new->maxage_delay = OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
+  new->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
   new->maxage_lsa = route_table_init();
   new->t_maxage_walker =
     thread_add_timer (master, ospf_lsa_maxage_walker,
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index fb57bf5..4242aa0 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -24,22 +24,13 @@
 #define _ZEBRA_OSPFD_H
 
 #include <zebra.h>
+#include "libospf.h"
 
 #include "filter.h"
 #include "log.h"
 
 #define OSPF_VERSION            2
 
-/* Default protocol, port number. */
-#ifndef IPPROTO_OSPFIGP
-#define IPPROTO_OSPFIGP         89
-#endif /* IPPROTO_OSPFIGP */
-
-/* IP precedence. */
-#ifndef IPTOS_PREC_INTERNETCONTROL
-#define IPTOS_PREC_INTERNETCONTROL	0xC0
-#endif /* IPTOS_PREC_INTERNETCONTROL */
-
 /* VTY port number. */
 #define OSPF_VTY_PORT          2604
 
@@ -50,29 +41,11 @@
 /* Default configuration file name for ospfd. */
 #define OSPF_DEFAULT_CONFIG   "ospfd.conf"
 
-/* Architectual Constants */
-#ifdef DEBUG
-#define OSPF_LS_REFRESH_TIME                    60
-#else
-#define OSPF_LS_REFRESH_TIME                  1800
-#endif
-#define OSPF_MIN_LS_INTERVAL                     5
-#define OSPF_MIN_LS_ARRIVAL                      1
-#define OSPF_LSA_INITIAL_AGE                     0	/* useful for debug */
-#define OSPF_LSA_MAXAGE                       3600
-#define OSPF_CHECK_AGE                         300
-#define OSPF_LSA_MAXAGE_DIFF                   900
-#define OSPF_LS_INFINITY                  0xffffff
-#define OSPF_DEFAULT_DESTINATION        0x00000000      /* 0.0.0.0 */
-#define OSPF_INITIAL_SEQUENCE_NUMBER    0x80000001
-#define OSPF_MAX_SEQUENCE_NUMBER        0x7fffffff
-
 #define OSPF_NSSA_TRANS_STABLE_DEFAULT		40
 
 #define OSPF_ALLSPFROUTERS              0xe0000005      /* 224.0.0.5 */
 #define OSPF_ALLDROUTERS                0xe0000006      /* 224.0.0.6 */
 
-#define OSPF_AREA_BACKBONE              0x00000000      /* 0.0.0.0 */
 
 /* OSPF Authentication Type. */
 #define OSPF_AUTH_NULL                      0
@@ -85,30 +58,6 @@
    been given or not in VLink command handlers */
 #define OSPF_AUTH_CMD_NOTSEEN              -2
 
-/* OSPF SPF timer values. */
-#define OSPF_SPF_DELAY_DEFAULT              200
-#define OSPF_SPF_HOLDTIME_DEFAULT           1000
-#define OSPF_SPF_MAX_HOLDTIME_DEFAULT	    10000
-
-/* OSPF interface default values. */
-#define OSPF_OUTPUT_COST_DEFAULT           10
-#define OSPF_OUTPUT_COST_INFINITE	   UINT16_MAX
-#define OSPF_ROUTER_DEAD_INTERVAL_DEFAULT  40
-#define OSPF_ROUTER_DEAD_INTERVAL_MINIMAL   1
-#define OSPF_HELLO_INTERVAL_DEFAULT        10
-#define OSPF_ROUTER_PRIORITY_DEFAULT        1
-#define OSPF_RETRANSMIT_INTERVAL_DEFAULT    5
-#define OSPF_TRANSMIT_DELAY_DEFAULT         1
-#define OSPF_DEFAULT_BANDWIDTH		 10000	/* Kbps */
-
-#define OSPF_DEFAULT_REF_BANDWIDTH	100000  /* Kbps */
-
-#define OSPF_POLL_INTERVAL_DEFAULT         60
-#define OSPF_NEIGHBOR_PRIORITY_DEFAULT      0
-
-#define OSPF_MTU_IGNORE_DEFAULT             0
-#define OSPF_FAST_HELLO_DEFAULT             0
-
 /* OSPF options. */
 #define OSPF_OPTION_T                    0x01  /* TOS. */
 #define OSPF_OPTION_E                    0x02
@@ -262,10 +211,8 @@
   struct thread *t_opaque_lsa_self;	/* Type-11 Opaque-LSAs origin event. */
 #endif /* HAVE_OPAQUE_LSA */
 
-#define OSFP_LSA_MAXAGE_REMOVE_DELAY_DEFAULT	60
   unsigned int maxage_delay;		/* Delay on Maxage remover timer, sec */
   struct thread *t_maxage;              /* MaxAge LSA remover timer. */
-#define OSPF_LSA_MAXAGE_CHECK_INTERVAL		30
   struct thread *t_maxage_walker;       /* MaxAge LSA checking timer. */
 
   struct thread *t_deferred_shutdown;	/* deferred/stub-router shutdown timer*/